@farm.js/core 0.1.0-beta.75 → 0.1.0-beta.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-runtime.cjs +7 -0
- package/dist/agent-runtime.cjs.map +1 -1
- package/dist/agent-runtime.mjs +7 -0
- package/dist/agent-runtime.mjs.map +1 -1
- package/dist/{app-BkCh7H09.d.mts → app-Bq-Tr90H.d.mts} +2 -0
- package/dist/{app-CZIEOZIa.d.ts → app-CQ6uhLEj.d.ts} +2 -0
- package/dist/{chunk-TWN6IBIL.mjs → chunk-ENS436YL.mjs} +2 -2
- package/dist/{chunk-IIKQBOGZ.mjs → chunk-MV5WATSI.mjs} +2 -2
- package/dist/{chunk-IIKQBOGZ.mjs.map → chunk-MV5WATSI.mjs.map} +1 -1
- package/dist/{chunk-S6FO7OXA.mjs → chunk-NN6KJF7I.mjs} +52 -7
- package/dist/chunk-NN6KJF7I.mjs.map +1 -0
- package/dist/{chunk-DKD7DGTE.mjs → chunk-OL7GH5ZC.mjs} +2 -2
- package/dist/{chunk-UGK7TW2V.mjs → chunk-P57PPOQL.mjs} +18 -6
- package/dist/chunk-P57PPOQL.mjs.map +1 -0
- package/dist/client/lifecycle.mjs +2 -2
- package/dist/client-plugins.cjs +1 -1
- package/dist/client-plugins.cjs.map +1 -1
- package/dist/client-plugins.mjs +2 -2
- package/dist/client.cjs +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.mjs +2 -2
- package/dist/index.cjs +75 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +5 -5
- package/dist/internal/build-runtime.cjs +58 -6
- package/dist/internal/build-runtime.cjs.map +1 -1
- package/dist/internal/build-runtime.mjs +3 -3
- package/dist/internal/client-runtime.cjs +1 -1
- package/dist/internal/client-runtime.cjs.map +1 -1
- package/dist/internal/client-runtime.mjs +2 -2
- package/dist/internal/product-telemetry-runtime.cjs +1 -1
- package/dist/internal/product-telemetry-runtime.cjs.map +1 -1
- package/dist/internal/product-telemetry-runtime.mjs +1 -1
- package/dist/plugin.cjs +51 -6
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.mjs +2 -2
- package/dist/server-plugins.cjs +17 -5
- package/dist/server-plugins.cjs.map +1 -1
- package/dist/server-plugins.mjs +1 -1
- package/dist/server.cjs +68 -11
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.mts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.mjs +3 -3
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.mjs +1 -1
- package/dist/vite.cjs +51 -6
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +2 -2
- package/package.json +1 -1
- package/dist/chunk-S6FO7OXA.mjs.map +0 -1
- package/dist/chunk-UGK7TW2V.mjs.map +0 -1
- /package/dist/{chunk-TWN6IBIL.mjs.map → chunk-ENS436YL.mjs.map} +0 -0
- /package/dist/{chunk-DKD7DGTE.mjs.map → chunk-OL7GH5ZC.mjs.map} +0 -0
package/dist/plugin.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import "./chunk-RQ633A5I.mjs";
|
|
7
7
|
import {
|
|
8
8
|
farmPlugin
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-NN6KJF7I.mjs";
|
|
10
10
|
import "./chunk-4RDYOSFE.mjs";
|
|
11
11
|
import "./chunk-C6JEXU6F.mjs";
|
|
12
12
|
import "./chunk-AMZZCRQ7.mjs";
|
|
@@ -66,7 +66,7 @@ import "./chunk-RBRLLZL5.mjs";
|
|
|
66
66
|
import "./chunk-WZ5QFROO.mjs";
|
|
67
67
|
import "./chunk-ZRBCBOEX.mjs";
|
|
68
68
|
import "./chunk-FXG2PS27.mjs";
|
|
69
|
-
import "./chunk-
|
|
69
|
+
import "./chunk-MV5WATSI.mjs";
|
|
70
70
|
import "./chunk-I3FMD5VJ.mjs";
|
|
71
71
|
import "./chunk-OMQWEX4N.mjs";
|
|
72
72
|
import "./chunk-44ZCFSKE.mjs";
|
package/dist/server-plugins.cjs
CHANGED
|
@@ -404,17 +404,18 @@ function selectEncoding(header) {
|
|
|
404
404
|
return brotli >= gzip ? "br" : "gzip";
|
|
405
405
|
}
|
|
406
406
|
__name(selectEncoding, "selectEncoding");
|
|
407
|
-
function
|
|
408
|
-
if (request.method
|
|
407
|
+
function isCompressionEligible(request, response) {
|
|
408
|
+
if (request.method !== "HEAD" && !response.body || response.status === 204 || response.status === 205 || response.status === 304 || response.headers.has("content-encoding") || response.headers.has("content-range") || response.headers.get("cache-control")?.toLowerCase().includes("no-transform")) {
|
|
409
409
|
return false;
|
|
410
410
|
}
|
|
411
411
|
const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
|
|
412
412
|
return contentType !== "text/event-stream";
|
|
413
413
|
}
|
|
414
|
-
__name(
|
|
414
|
+
__name(isCompressionEligible, "isCompressionEligible");
|
|
415
415
|
function appendVary(headers, value) {
|
|
416
416
|
const current = headers.get("vary");
|
|
417
417
|
const values = current ? current.split(",").map((item) => item.trim()).filter(Boolean) : [];
|
|
418
|
+
if (values.includes("*")) return;
|
|
418
419
|
if (!values.some((item) => item.toLowerCase() === value.toLowerCase())) {
|
|
419
420
|
values.push(value);
|
|
420
421
|
}
|
|
@@ -440,6 +441,16 @@ function compressResponse(response, encoding) {
|
|
|
440
441
|
});
|
|
441
442
|
}
|
|
442
443
|
__name(compressResponse, "compressResponse");
|
|
444
|
+
function varyIdentityResponse(response) {
|
|
445
|
+
const headers = new Headers(response.headers);
|
|
446
|
+
appendVary(headers, "Accept-Encoding");
|
|
447
|
+
return new Response(response.body, {
|
|
448
|
+
status: response.status,
|
|
449
|
+
statusText: response.statusText,
|
|
450
|
+
headers
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
__name(varyIdentityResponse, "varyIdentityResponse");
|
|
443
454
|
function createCompressionPlugin({
|
|
444
455
|
beforeRequest: overrideBeforeRequest,
|
|
445
456
|
afterResponse: overrideAfterResponse
|
|
@@ -449,9 +460,10 @@ function createCompressionPlugin({
|
|
|
449
460
|
enforce: "post",
|
|
450
461
|
runtime: {
|
|
451
462
|
after({ request, response, isProd }) {
|
|
452
|
-
if (!isProd || !
|
|
463
|
+
if (!isProd || !isCompressionEligible(request, response)) return;
|
|
464
|
+
if (request.method === "HEAD") return varyIdentityResponse(response);
|
|
453
465
|
const encoding = selectEncoding(request.headers.get("accept-encoding") ?? "");
|
|
454
|
-
if (!encoding) return;
|
|
466
|
+
if (!encoding) return varyIdentityResponse(response);
|
|
455
467
|
return compressResponse(response, encoding);
|
|
456
468
|
}
|
|
457
469
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server-plugins.ts","../src/navigation-errors.ts","../src/i18n/routing.ts","../src/plugins/route-pattern.ts","../src/plugins/redirects.ts","../src/plugins/headers.ts","../src/plugins/rewrites.ts","../src/plugins/env.ts","../src/plugins/compression.ts","../src/plugins/logger.ts"],"sourcesContent":["// Server-side plugins export\nexport {\n createRedirectsPlugin,\n createHeadersPlugin,\n createRewritesPlugin,\n createEnvPlugin,\n createCompressionPlugin,\n createLoggerPlugin,\n} from \"./plugins\";\n\nexport type {\n FarmPlugin,\n FarmPluginContext,\n FarmPluginLifecycle,\n FarmRequestPluginContext,\n FarmRequestStore,\n} from \"./plugin\";\nexport type { RedirectConfig, HeaderConfig, RewriteConfig } from \"./config\";\n","export type FarmRedirectStatus = 301 | 302 | 303 | 307 | 308;\n\nexport interface FarmRedirectSignal {\n url: string;\n status: FarmRedirectStatus;\n}\n\nconst REDIRECT_ERROR_CODE = \"FARM_REDIRECT\";\nconst NOT_FOUND_ERROR_CODE = \"FARM_NOT_FOUND\";\nconst REDIRECT_ERROR_SYMBOL = Symbol.for(\"farm.navigation.redirect\");\nconst NOT_FOUND_ERROR_SYMBOL = Symbol.for(\"farm.navigation.notFound\");\n\ntype FarmNavigationError = Error & {\n digest: string;\n [REDIRECT_ERROR_SYMBOL]?: FarmRedirectSignal;\n [NOT_FOUND_ERROR_SYMBOL]?: true;\n};\n\nexport function redirect(url: string, status: FarmRedirectStatus = 307): never {\n throw createRedirectError(url, status);\n}\n\nexport function permanentRedirect(url: string): never {\n redirect(url, 308);\n}\n\nexport function notFound(): never {\n const error = new Error(NOT_FOUND_ERROR_CODE) as FarmNavigationError;\n error.digest = NOT_FOUND_ERROR_CODE;\n error[NOT_FOUND_ERROR_SYMBOL] = true;\n throw error;\n}\n\nexport function isFarmRedirectError(error: unknown): boolean {\n return Boolean(getFarmRedirectError(error));\n}\n\nexport function getFarmRedirectError(error: unknown): FarmRedirectSignal | null {\n if (!error || typeof error !== \"object\") return null;\n const candidate = error as Partial<FarmNavigationError>;\n if (candidate[REDIRECT_ERROR_SYMBOL]) {\n return candidate[REDIRECT_ERROR_SYMBOL] as FarmRedirectSignal;\n }\n\n if (\n typeof candidate.digest === \"string\" &&\n candidate.digest.startsWith(`${REDIRECT_ERROR_CODE};`)\n ) {\n const [, status, ...urlParts] = candidate.digest.split(\";\");\n const parsedStatus = Number(status);\n if (isFarmRedirectStatus(parsedStatus)) {\n return {\n status: parsedStatus,\n url: urlParts.join(\";\"),\n };\n }\n }\n\n return null;\n}\n\nexport function isFarmNotFoundError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const candidate = error as Partial<FarmNavigationError>;\n return Boolean(candidate[NOT_FOUND_ERROR_SYMBOL] || candidate.digest === NOT_FOUND_ERROR_CODE);\n}\n\nfunction createRedirectError(url: string, status: FarmRedirectStatus): FarmNavigationError {\n const error = new Error(`${REDIRECT_ERROR_CODE};${status};${url}`) as FarmNavigationError;\n error.digest = `${REDIRECT_ERROR_CODE};${status};${url}`;\n error[REDIRECT_ERROR_SYMBOL] = { url, status };\n return error;\n}\n\nexport function isFarmRedirectStatus(status: unknown): status is FarmRedirectStatus {\n return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;\n}\n","import type { FarmI18nDirection, FarmI18nRouting, ResolvedFarmI18nConfig } from \"./types\";\n\nexport interface FarmLocalePathConfig {\n locales: readonly string[];\n defaultLocale: string;\n routing: FarmI18nRouting;\n}\n\nexport interface FarmLocalePathMatch {\n locale?: string;\n pathname: string;\n explicit: boolean;\n}\n\nconst RTL_LANGUAGES = new Set([\n \"ar\",\n \"arc\",\n \"ckb\",\n \"dv\",\n \"fa\",\n \"he\",\n \"ku\",\n \"nqo\",\n \"ps\",\n \"sd\",\n \"syr\",\n \"ug\",\n \"ur\",\n \"yi\",\n]);\n\nexport function resolveFarmLocalePath(\n pathname: string,\n config: FarmLocalePathConfig,\n): FarmLocalePathMatch {\n const normalized = normalizePathname(pathname);\n if (config.routing === \"none\") {\n return { pathname: normalized, explicit: false };\n }\n\n const segments = normalized.split(\"/\").filter(Boolean);\n const firstSegment = segments[0];\n const locale = config.locales.find(\n (candidate) => candidate.toLowerCase() === firstSegment?.toLowerCase(),\n );\n if (!locale) {\n return { pathname: normalized, explicit: false };\n }\n\n const remaining = segments.slice(1);\n return {\n locale,\n pathname: remaining.length > 0 ? `/${remaining.join(\"/\")}` : \"/\",\n explicit: true,\n };\n}\n\nexport function stripFarmLocaleFromPathname(\n pathname: string,\n config: FarmLocalePathConfig,\n): string {\n return resolveFarmLocalePath(pathname, config).pathname;\n}\n\nexport function localizeFarmPathname(\n pathname: string,\n locale: string,\n config: FarmLocalePathConfig,\n): string {\n const internalPathname = resolveFarmLocalePath(pathname, config).pathname;\n if (config.routing === \"none\") return internalPathname;\n if (config.routing === \"prefix-except-default\" && locale === config.defaultLocale) {\n return internalPathname;\n }\n return internalPathname === \"/\" ? `/${locale}` : `/${locale}${internalPathname}`;\n}\n\nexport function localizeFarmHref(\n href: string,\n locale: string,\n config: FarmLocalePathConfig,\n): string {\n if (!href.startsWith(\"/\") || href.startsWith(\"//\")) return href;\n const url = new URL(href, \"http://farm.local\");\n url.pathname = localizeFarmPathname(url.pathname, locale, config);\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nexport function getFarmLocaleDirection(\n locale: string,\n direction: ResolvedFarmI18nConfig[\"direction\"] | undefined,\n): FarmI18nDirection {\n const configured = direction?.[locale];\n if (configured) return configured;\n const language = locale.split(\"-\")[0]?.toLowerCase() || locale.toLowerCase();\n return RTL_LANGUAGES.has(language) ? \"rtl\" : \"ltr\";\n}\n\nfunction normalizePathname(pathname: string): string {\n const withLeadingSlash = pathname.startsWith(\"/\") ? pathname : `/${pathname}`;\n if (withLeadingSlash === \"/\") return \"/\";\n return withLeadingSlash.replace(/\\/{2,}/g, \"/\").replace(/\\/$/, \"\") || \"/\";\n}\n","import { localizeFarmHref, resolveFarmLocalePath } from \"../i18n/routing\";\nimport type { ResolvedFarmI18nConfig } from \"../i18n/types\";\n\ntype ConfigRoutePatternToken =\n | { kind: \"param\"; name: string; captureIndex: number }\n | { kind: \"wildcard\"; captureIndex: number };\n\nexport interface CompiledConfigRoutePattern {\n regex: RegExp;\n tokens: ConfigRoutePatternToken[];\n}\n\nexport function resolveConfigRoutePathname(\n pathname: string,\n i18n?: ResolvedFarmI18nConfig,\n): { pathname: string; locale?: string } {\n if (!i18n?.enabled) return { pathname };\n const match = resolveFarmLocalePath(pathname, i18n);\n return { pathname: match.pathname, locale: match.locale };\n}\n\nexport function localizeConfigRouteDestination(\n destination: string,\n locale: string | undefined,\n i18n?: ResolvedFarmI18nConfig,\n): string {\n return locale && i18n?.enabled ? localizeFarmHref(destination, locale, i18n) : destination;\n}\n\nfunction escapeRegexCharacter(character: string): string {\n return /[\\\\^$.*+?()[\\]{}|]/.test(character) ? `\\\\${character}` : character;\n}\n\nexport function compileConfigRoutePattern(source: string): CompiledConfigRoutePattern {\n const tokens: ConfigRoutePatternToken[] = [];\n let pattern = \"\";\n let captureIndex = 1;\n\n for (let index = 0; index < source.length; ) {\n const rest = source.slice(index);\n const parameter = rest.match(/^:([A-Za-z0-9_]+)(\\*)?/);\n if (parameter) {\n tokens.push({ kind: \"param\", name: parameter[1], captureIndex });\n pattern += parameter[2] ? \"(.*)\" : \"([^/]+)\";\n captureIndex += 1;\n index += parameter[0].length;\n continue;\n }\n\n if (source[index] === \"*\") {\n tokens.push({ kind: \"wildcard\", captureIndex });\n pattern += \"(.*)\";\n captureIndex += 1;\n index += 1;\n continue;\n }\n\n pattern += escapeRegexCharacter(source[index]);\n index += 1;\n }\n\n return { regex: new RegExp(`^${pattern}$`), tokens };\n}\n\nexport function interpolateConfigRouteDestination(\n destination: string,\n match: RegExpMatchArray,\n tokens: readonly ConfigRoutePatternToken[],\n): string {\n const namedCaptures = new Map<string, string>();\n const wildcardCaptures: string[] = [];\n\n for (const token of tokens) {\n const value = match[token.captureIndex] || \"\";\n if (token.kind === \"param\") {\n namedCaptures.set(token.name, value);\n } else {\n wildcardCaptures.push(value);\n }\n }\n\n let result = \"\";\n let wildcardIndex = 0;\n for (let index = 0; index < destination.length; ) {\n const rest = destination.slice(index);\n const parameter = rest.match(/^:([A-Za-z0-9_]+)(\\*)?/);\n if (parameter) {\n const value = namedCaptures.get(parameter[1]);\n result += value === undefined ? parameter[0] : value;\n index += parameter[0].length;\n continue;\n }\n\n const capture = rest.match(/^\\$(\\d+)/);\n if (capture) {\n result += match[Number(capture[1])] || \"\";\n index += capture[0].length;\n continue;\n }\n\n if (destination[index] === \"*\") {\n result += wildcardCaptures[wildcardIndex] || \"\";\n wildcardIndex += 1;\n index += 1;\n continue;\n }\n\n result += destination[index];\n index += 1;\n }\n\n return result;\n}\n","import type { FarmPlugin, FarmPluginContext } from \"../plugin\";\nimport type { RedirectConfig } from \"../config\";\nimport type { FarmRequest, FarmResponse } from \"../types\";\nimport type { ResolvedFarmI18nConfig } from \"../i18n/types\";\nimport { isFarmRedirectStatus } from \"../navigation-errors\";\nimport {\n compileConfigRoutePattern,\n interpolateConfigRouteDestination,\n localizeConfigRouteDestination,\n resolveConfigRoutePathname,\n} from \"./route-pattern\";\n\nexport function createRedirectsPlugin(\n redirects: RedirectConfig[],\n {\n beforeRequest: overrideBeforeRequest,\n afterResponse: overrideAfterResponse,\n i18n,\n }: {\n beforeRequest?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n afterResponse?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n i18n?: ResolvedFarmI18nConfig;\n } = {},\n): FarmPlugin {\n for (const redirect of redirects) {\n if (redirect.statusCode !== undefined && !isFarmRedirectStatus(redirect.statusCode)) {\n throw new RangeError(\n `Redirect \"${redirect.source}\" statusCode must be one of 301, 302, 303, 307, or 308.`,\n );\n }\n }\n const compiledRedirects = redirects.map((redirect) => ({\n redirect,\n pattern: compileConfigRoutePattern(redirect.source),\n }));\n\n return {\n name: \"farm:redirects\",\n enforce: \"pre\",\n async beforeRequest(req, res, context) {\n if (overrideBeforeRequest) {\n await overrideBeforeRequest(req, res, context);\n }\n const url = new URL(req.url || \"/\", `http://${req.headers.host}`);\n const routePath = resolveConfigRoutePathname(url.pathname, i18n);\n const pathname = routePath.pathname;\n\n for (const { redirect, pattern } of compiledRedirects) {\n const match = pathname.match(pattern.regex);\n if (match) {\n const destination = localizeConfigRouteDestination(\n interpolateConfigRouteDestination(redirect.destination, match, pattern.tokens),\n routePath.locale,\n i18n,\n );\n\n const statusCode = redirect.statusCode ?? (redirect.permanent ? 308 : 307);\n\n res.writeHead(statusCode, {\n Location: destination,\n });\n res.end();\n return;\n }\n }\n },\n\n async afterResponse(req, res, context) {\n if (overrideAfterResponse) {\n await overrideAfterResponse(req, res, context);\n }\n },\n };\n}\n","import type { FarmPlugin, FarmPluginContext } from \"../plugin\";\nimport type { HeaderConfig } from \"../config\";\nimport type { FarmRequest, FarmResponse } from \"../types\";\nimport type { ResolvedFarmI18nConfig } from \"../i18n/types\";\nimport { compileConfigRoutePattern, resolveConfigRoutePathname } from \"./route-pattern\";\n\nconst FARM_CONFIG_HEADERS_FINALIZER = Symbol.for(\"farm.configHeadersFinalizer\");\n\nfunction appendConfiguredLinkHeader(res: FarmResponse, value: string): void {\n const current = res.getHeader(\"Link\");\n if (current === undefined) {\n res.setHeader(\"Link\", value);\n return;\n }\n\n const currentValue = Array.isArray(current) ? current.join(\", \") : String(current);\n if (currentValue !== value && !currentValue.endsWith(`, ${value}`)) {\n res.setHeader(\"Link\", `${currentValue}, ${value}`);\n }\n}\n\nfunction applyResponseHeaders(\n res: FarmResponse,\n matchedHeaders: readonly HeaderConfig[\"headers\"][],\n): void {\n for (const headers of matchedHeaders) {\n for (const header of headers) {\n if (header.key.toLowerCase() === \"link\") {\n appendConfiguredLinkHeader(res, header.value);\n } else {\n res.setHeader(header.key, header.value);\n }\n }\n }\n}\n\nfunction applyWriteHeadHeaders(res: FarmResponse, headers: unknown): void {\n if (Array.isArray(headers)) {\n for (let index = 0; index + 1 < headers.length; index += 2) {\n res.setHeader(String(headers[index]), headers[index + 1]);\n }\n return;\n }\n\n if (!headers || typeof headers !== \"object\") return;\n for (const [key, value] of Object.entries(headers)) {\n if (value !== undefined) res.setHeader(key, value);\n }\n}\n\nexport function createHeadersPlugin(\n headers: HeaderConfig[],\n {\n beforeRequest: overrideBeforeRequest,\n afterResponse: overrideAfterResponse,\n i18n,\n }: {\n beforeRequest?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n afterResponse?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n i18n?: ResolvedFarmI18nConfig;\n } = {},\n): FarmPlugin {\n const compiledHeaders = headers.map((config) => ({\n config,\n pattern: compileConfigRoutePattern(config.source),\n }));\n\n return {\n name: \"farm:headers\",\n enforce: \"pre\",\n\n async beforeRequest(req, res, context) {\n if (overrideBeforeRequest) {\n await overrideBeforeRequest(req, res, context);\n }\n const url = new URL(req.url || \"/\", `http://${req.headers.host}`);\n const pathname = resolveConfigRoutePathname(url.pathname, i18n).pathname;\n const matchedHeaders = compiledHeaders\n .filter(({ pattern }) => pattern.regex.test(pathname))\n .map(({ config }) => config.headers);\n\n applyResponseHeaders(res, matchedHeaders);\n\n const responseWithFinalizer = res as FarmResponse & {\n [FARM_CONFIG_HEADERS_FINALIZER]?: boolean;\n };\n if (matchedHeaders.length === 0 || responseWithFinalizer[FARM_CONFIG_HEADERS_FINALIZER]) {\n return;\n }\n\n responseWithFinalizer[FARM_CONFIG_HEADERS_FINALIZER] = true;\n const writeHead = res.writeHead;\n res.writeHead = ((statusCode: number, ...args: unknown[]) => {\n const statusMessage = typeof args[0] === \"string\" ? (args.shift() as string) : undefined;\n applyWriteHeadHeaders(res, args[0]);\n applyResponseHeaders(res, matchedHeaders);\n return statusMessage === undefined\n ? (writeHead as any).call(res, statusCode)\n : (writeHead as any).call(res, statusCode, statusMessage);\n }) as FarmResponse[\"writeHead\"];\n },\n\n async afterResponse(req, res, context) {\n if (overrideAfterResponse) {\n await overrideAfterResponse(req, res, context);\n }\n },\n };\n}\n","import type { FarmPlugin, FarmPluginContext } from \"../plugin\";\nimport type { RewriteConfig } from \"../config\";\nimport type { FarmRequest, FarmResponse } from \"../types\";\nimport type { ResolvedFarmI18nConfig } from \"../i18n/types\";\nimport {\n compileConfigRoutePattern,\n interpolateConfigRouteDestination,\n localizeConfigRouteDestination,\n resolveConfigRoutePathname,\n} from \"./route-pattern\";\n\nexport const FARM_CONFIG_REWRITES_PLUGIN_NAME = \"farm:rewrites\";\n\nexport function createRewritesPlugin(\n rewrites: RewriteConfig[],\n {\n beforeRequest: overrideBeforeRequest,\n afterResponse: overrideAfterResponse,\n i18n,\n }: {\n beforeRequest?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n afterResponse?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n i18n?: ResolvedFarmI18nConfig;\n } = {},\n): FarmPlugin {\n const compiledRewrites = rewrites.map((rewrite) => ({\n rewrite,\n pattern: compileConfigRoutePattern(rewrite.source),\n }));\n\n return {\n name: FARM_CONFIG_REWRITES_PLUGIN_NAME,\n enforce: \"pre\",\n\n async beforeRequest(req, res, context) {\n if (overrideBeforeRequest) {\n await overrideBeforeRequest(req, res, context);\n }\n const url = new URL(req.url || \"/\", `http://${req.headers.host}`);\n const routePath = resolveConfigRoutePathname(url.pathname, i18n);\n const pathname = routePath.pathname;\n\n for (const { rewrite, pattern } of compiledRewrites) {\n const match = pathname.match(pattern.regex);\n if (match) {\n const newPath = localizeConfigRouteDestination(\n interpolateConfigRouteDestination(rewrite.destination, match, pattern.tokens),\n routePath.locale,\n i18n,\n );\n const destinationUrl = new URL(newPath, url);\n if (!destinationUrl.search && url.search) {\n destinationUrl.search = url.search;\n }\n req.url =\n destinationUrl.origin === url.origin\n ? destinationUrl.pathname + destinationUrl.search\n : destinationUrl.href;\n break;\n }\n }\n },\n\n async afterResponse(req, res, context) {\n if (overrideAfterResponse) {\n await overrideAfterResponse(req, res, context);\n }\n },\n };\n}\n","import type { FarmPlugin, FarmPluginContext } from \"../plugin\";\nimport type { FarmRequest, FarmResponse } from \"../types\";\n\nexport function createEnvPlugin(\n env: Record<string, string>,\n {\n beforeRequest: overrideBeforeRequest,\n afterResponse: overrideAfterResponse,\n }: {\n beforeRequest?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n afterResponse?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n } = {},\n): FarmPlugin {\n return {\n name: \"farm:env\",\n\n configResolved(config, context) {\n for (const [key, value] of Object.entries(env)) {\n process.env[key] = value;\n }\n },\n\n async beforeRequest(req, res, context) {\n if (overrideBeforeRequest) {\n await overrideBeforeRequest(req, res, context);\n }\n },\n\n async afterResponse(req, res, context) {\n if (overrideAfterResponse) {\n await overrideAfterResponse(req, res, context);\n }\n },\n };\n}\n","import type { FarmPlugin, FarmPluginContext } from \"../plugin\";\nimport type { FarmRequest, FarmResponse } from \"../types\";\nimport { Readable } from \"node:stream\";\nimport { constants, createBrotliCompress, createGzip } from \"node:zlib\";\n\ntype SupportedEncoding = \"br\" | \"gzip\";\n\nconst Q_VALUE = /^(?:0(?:\\.\\d{0,3})?|1(?:\\.0{0,3})?)$/;\n\nfunction parseEncodingQuality(header: string): Map<string, number> {\n const qualities = new Map<string, number>();\n\n for (const item of header.split(\",\")) {\n const [rawEncoding, ...parameters] = item.trim().split(\";\");\n const encoding = rawEncoding?.trim().toLowerCase();\n if (!encoding) continue;\n\n let quality = 1;\n for (const parameter of parameters) {\n const [rawName, rawValue] = parameter.split(\"=\", 2);\n if (rawName?.trim().toLowerCase() !== \"q\") continue;\n const value = rawValue?.trim() ?? \"\";\n quality = Q_VALUE.test(value) ? Number(value) : 0;\n }\n\n qualities.set(encoding, Math.max(qualities.get(encoding) ?? 0, quality));\n }\n\n return qualities;\n}\n\nfunction selectEncoding(header: string): SupportedEncoding | undefined {\n if (!header.trim()) return undefined;\n\n const qualities = parseEncodingQuality(header);\n const wildcard = qualities.get(\"*\") ?? 0;\n const quality = (encoding: SupportedEncoding) => qualities.get(encoding) ?? wildcard;\n const brotli = quality(\"br\");\n const gzip = quality(\"gzip\");\n\n if (brotli <= 0 && gzip <= 0) return undefined;\n return brotli >= gzip ? \"br\" : \"gzip\";\n}\n\nfunction canCompress(request: Request, response: Response): boolean {\n if (\n request.method === \"HEAD\" ||\n !response.body ||\n response.status === 204 ||\n response.status === 205 ||\n response.status === 304 ||\n response.headers.has(\"content-encoding\") ||\n response.headers.has(\"content-range\") ||\n response.headers.get(\"cache-control\")?.toLowerCase().includes(\"no-transform\")\n ) {\n return false;\n }\n\n const contentType = response.headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n return contentType !== \"text/event-stream\";\n}\n\nfunction appendVary(headers: Headers, value: string): void {\n const current = headers.get(\"vary\");\n const values = current\n ? current\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean)\n : [];\n if (!values.some((item) => item.toLowerCase() === value.toLowerCase())) {\n values.push(value);\n }\n headers.set(\"vary\", values.join(\", \"));\n}\n\nfunction compressResponse(response: Response, encoding: SupportedEncoding): Response {\n const compressor =\n encoding === \"br\" ? createBrotliCompress() : createGzip({ flush: constants.Z_SYNC_FLUSH });\n const input = Readable.fromWeb(response.body as any);\n const output = input.pipe(compressor);\n const headers = new Headers(response.headers);\n\n headers.set(\"content-encoding\", encoding);\n headers.delete(\"content-length\");\n appendVary(headers, \"Accept-Encoding\");\n\n const etag = headers.get(\"etag\");\n if (etag && !etag.startsWith(\"W/\")) {\n headers.set(\"etag\", `W/${etag}`);\n }\n\n return new Response(Readable.toWeb(output) as ReadableStream<Uint8Array>, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n\nexport function createCompressionPlugin({\n beforeRequest: overrideBeforeRequest,\n afterResponse: overrideAfterResponse,\n}: {\n beforeRequest?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n afterResponse?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n} = {}): FarmPlugin {\n return {\n name: \"farm:compression\",\n enforce: \"post\",\n\n runtime: {\n after({ request, response, isProd }) {\n if (!isProd || !canCompress(request, response)) return;\n\n const encoding = selectEncoding(request.headers.get(\"accept-encoding\") ?? \"\");\n if (!encoding) return;\n return compressResponse(response, encoding);\n },\n },\n\n async beforeRequest(req, res, context) {\n if (overrideBeforeRequest) {\n await overrideBeforeRequest(req, res, context);\n }\n },\n\n async afterResponse(req, res, context) {\n if (overrideAfterResponse) {\n await overrideAfterResponse(req, res, context);\n }\n },\n };\n}\n","import type { FarmPlugin, FarmPluginContext } from \"../plugin\";\nimport type { FarmResponse } from \"../types\";\nimport type { FarmRequest } from \"../types\";\n\nexport function createLoggerPlugin({\n beforeRequest,\n afterResponse,\n}: {\n beforeRequest?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n afterResponse?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n} = {}): FarmPlugin {\n const plugin: FarmPlugin = {\n name: \"farm:logger\",\n enforce: \"post\",\n };\n\n if (beforeRequest) {\n plugin.beforeRequest = async (req, res, context) => {\n await beforeRequest(req, res, context);\n };\n }\n if (afterResponse) {\n plugin.afterResponse = async (req, res, context) => {\n await afterResponse(req, res, context);\n };\n }\n\n return plugin;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/server-plugins.ts","../src/navigation-errors.ts","../src/i18n/routing.ts","../src/plugins/route-pattern.ts","../src/plugins/redirects.ts","../src/plugins/headers.ts","../src/plugins/rewrites.ts","../src/plugins/env.ts","../src/plugins/compression.ts","../src/plugins/logger.ts"],"sourcesContent":["// Server-side plugins export\nexport {\n createRedirectsPlugin,\n createHeadersPlugin,\n createRewritesPlugin,\n createEnvPlugin,\n createCompressionPlugin,\n createLoggerPlugin,\n} from \"./plugins\";\n\nexport type {\n FarmPlugin,\n FarmPluginContext,\n FarmPluginLifecycle,\n FarmRequestPluginContext,\n FarmRequestStore,\n} from \"./plugin\";\nexport type { RedirectConfig, HeaderConfig, RewriteConfig } from \"./config\";\n","export type FarmRedirectStatus = 301 | 302 | 303 | 307 | 308;\n\nexport interface FarmRedirectSignal {\n url: string;\n status: FarmRedirectStatus;\n}\n\nconst REDIRECT_ERROR_CODE = \"FARM_REDIRECT\";\nconst NOT_FOUND_ERROR_CODE = \"FARM_NOT_FOUND\";\nconst REDIRECT_ERROR_SYMBOL = Symbol.for(\"farm.navigation.redirect\");\nconst NOT_FOUND_ERROR_SYMBOL = Symbol.for(\"farm.navigation.notFound\");\n\ntype FarmNavigationError = Error & {\n digest: string;\n [REDIRECT_ERROR_SYMBOL]?: FarmRedirectSignal;\n [NOT_FOUND_ERROR_SYMBOL]?: true;\n};\n\nexport function redirect(url: string, status: FarmRedirectStatus = 307): never {\n throw createRedirectError(url, status);\n}\n\nexport function permanentRedirect(url: string): never {\n redirect(url, 308);\n}\n\nexport function notFound(): never {\n const error = new Error(NOT_FOUND_ERROR_CODE) as FarmNavigationError;\n error.digest = NOT_FOUND_ERROR_CODE;\n error[NOT_FOUND_ERROR_SYMBOL] = true;\n throw error;\n}\n\nexport function isFarmRedirectError(error: unknown): boolean {\n return Boolean(getFarmRedirectError(error));\n}\n\nexport function getFarmRedirectError(error: unknown): FarmRedirectSignal | null {\n if (!error || typeof error !== \"object\") return null;\n const candidate = error as Partial<FarmNavigationError>;\n if (candidate[REDIRECT_ERROR_SYMBOL]) {\n return candidate[REDIRECT_ERROR_SYMBOL] as FarmRedirectSignal;\n }\n\n if (\n typeof candidate.digest === \"string\" &&\n candidate.digest.startsWith(`${REDIRECT_ERROR_CODE};`)\n ) {\n const [, status, ...urlParts] = candidate.digest.split(\";\");\n const parsedStatus = Number(status);\n if (isFarmRedirectStatus(parsedStatus)) {\n return {\n status: parsedStatus,\n url: urlParts.join(\";\"),\n };\n }\n }\n\n return null;\n}\n\nexport function isFarmNotFoundError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const candidate = error as Partial<FarmNavigationError>;\n return Boolean(candidate[NOT_FOUND_ERROR_SYMBOL] || candidate.digest === NOT_FOUND_ERROR_CODE);\n}\n\nfunction createRedirectError(url: string, status: FarmRedirectStatus): FarmNavigationError {\n const error = new Error(`${REDIRECT_ERROR_CODE};${status};${url}`) as FarmNavigationError;\n error.digest = `${REDIRECT_ERROR_CODE};${status};${url}`;\n error[REDIRECT_ERROR_SYMBOL] = { url, status };\n return error;\n}\n\nexport function isFarmRedirectStatus(status: unknown): status is FarmRedirectStatus {\n return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;\n}\n","import type { FarmI18nDirection, FarmI18nRouting, ResolvedFarmI18nConfig } from \"./types\";\n\nexport interface FarmLocalePathConfig {\n locales: readonly string[];\n defaultLocale: string;\n routing: FarmI18nRouting;\n}\n\nexport interface FarmLocalePathMatch {\n locale?: string;\n pathname: string;\n explicit: boolean;\n}\n\nconst RTL_LANGUAGES = new Set([\n \"ar\",\n \"arc\",\n \"ckb\",\n \"dv\",\n \"fa\",\n \"he\",\n \"ku\",\n \"nqo\",\n \"ps\",\n \"sd\",\n \"syr\",\n \"ug\",\n \"ur\",\n \"yi\",\n]);\n\nexport function resolveFarmLocalePath(\n pathname: string,\n config: FarmLocalePathConfig,\n): FarmLocalePathMatch {\n const normalized = normalizePathname(pathname);\n if (config.routing === \"none\") {\n return { pathname: normalized, explicit: false };\n }\n\n const segments = normalized.split(\"/\").filter(Boolean);\n const firstSegment = segments[0];\n const locale = config.locales.find(\n (candidate) => candidate.toLowerCase() === firstSegment?.toLowerCase(),\n );\n if (!locale) {\n return { pathname: normalized, explicit: false };\n }\n\n const remaining = segments.slice(1);\n return {\n locale,\n pathname: remaining.length > 0 ? `/${remaining.join(\"/\")}` : \"/\",\n explicit: true,\n };\n}\n\nexport function stripFarmLocaleFromPathname(\n pathname: string,\n config: FarmLocalePathConfig,\n): string {\n return resolveFarmLocalePath(pathname, config).pathname;\n}\n\nexport function localizeFarmPathname(\n pathname: string,\n locale: string,\n config: FarmLocalePathConfig,\n): string {\n const internalPathname = resolveFarmLocalePath(pathname, config).pathname;\n if (config.routing === \"none\") return internalPathname;\n if (config.routing === \"prefix-except-default\" && locale === config.defaultLocale) {\n return internalPathname;\n }\n return internalPathname === \"/\" ? `/${locale}` : `/${locale}${internalPathname}`;\n}\n\nexport function localizeFarmHref(\n href: string,\n locale: string,\n config: FarmLocalePathConfig,\n): string {\n if (!href.startsWith(\"/\") || href.startsWith(\"//\")) return href;\n const url = new URL(href, \"http://farm.local\");\n url.pathname = localizeFarmPathname(url.pathname, locale, config);\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nexport function getFarmLocaleDirection(\n locale: string,\n direction: ResolvedFarmI18nConfig[\"direction\"] | undefined,\n): FarmI18nDirection {\n const configured = direction?.[locale];\n if (configured) return configured;\n const language = locale.split(\"-\")[0]?.toLowerCase() || locale.toLowerCase();\n return RTL_LANGUAGES.has(language) ? \"rtl\" : \"ltr\";\n}\n\nfunction normalizePathname(pathname: string): string {\n const withLeadingSlash = pathname.startsWith(\"/\") ? pathname : `/${pathname}`;\n if (withLeadingSlash === \"/\") return \"/\";\n return withLeadingSlash.replace(/\\/{2,}/g, \"/\").replace(/\\/$/, \"\") || \"/\";\n}\n","import { localizeFarmHref, resolveFarmLocalePath } from \"../i18n/routing\";\nimport type { ResolvedFarmI18nConfig } from \"../i18n/types\";\n\ntype ConfigRoutePatternToken =\n | { kind: \"param\"; name: string; captureIndex: number }\n | { kind: \"wildcard\"; captureIndex: number };\n\nexport interface CompiledConfigRoutePattern {\n regex: RegExp;\n tokens: ConfigRoutePatternToken[];\n}\n\nexport function resolveConfigRoutePathname(\n pathname: string,\n i18n?: ResolvedFarmI18nConfig,\n): { pathname: string; locale?: string } {\n if (!i18n?.enabled) return { pathname };\n const match = resolveFarmLocalePath(pathname, i18n);\n return { pathname: match.pathname, locale: match.locale };\n}\n\nexport function localizeConfigRouteDestination(\n destination: string,\n locale: string | undefined,\n i18n?: ResolvedFarmI18nConfig,\n): string {\n return locale && i18n?.enabled ? localizeFarmHref(destination, locale, i18n) : destination;\n}\n\nfunction escapeRegexCharacter(character: string): string {\n return /[\\\\^$.*+?()[\\]{}|]/.test(character) ? `\\\\${character}` : character;\n}\n\nexport function compileConfigRoutePattern(source: string): CompiledConfigRoutePattern {\n const tokens: ConfigRoutePatternToken[] = [];\n let pattern = \"\";\n let captureIndex = 1;\n\n for (let index = 0; index < source.length; ) {\n const rest = source.slice(index);\n const parameter = rest.match(/^:([A-Za-z0-9_]+)(\\*)?/);\n if (parameter) {\n tokens.push({ kind: \"param\", name: parameter[1], captureIndex });\n pattern += parameter[2] ? \"(.*)\" : \"([^/]+)\";\n captureIndex += 1;\n index += parameter[0].length;\n continue;\n }\n\n if (source[index] === \"*\") {\n tokens.push({ kind: \"wildcard\", captureIndex });\n pattern += \"(.*)\";\n captureIndex += 1;\n index += 1;\n continue;\n }\n\n pattern += escapeRegexCharacter(source[index]);\n index += 1;\n }\n\n return { regex: new RegExp(`^${pattern}$`), tokens };\n}\n\nexport function interpolateConfigRouteDestination(\n destination: string,\n match: RegExpMatchArray,\n tokens: readonly ConfigRoutePatternToken[],\n): string {\n const namedCaptures = new Map<string, string>();\n const wildcardCaptures: string[] = [];\n\n for (const token of tokens) {\n const value = match[token.captureIndex] || \"\";\n if (token.kind === \"param\") {\n namedCaptures.set(token.name, value);\n } else {\n wildcardCaptures.push(value);\n }\n }\n\n let result = \"\";\n let wildcardIndex = 0;\n for (let index = 0; index < destination.length; ) {\n const rest = destination.slice(index);\n const parameter = rest.match(/^:([A-Za-z0-9_]+)(\\*)?/);\n if (parameter) {\n const value = namedCaptures.get(parameter[1]);\n result += value === undefined ? parameter[0] : value;\n index += parameter[0].length;\n continue;\n }\n\n const capture = rest.match(/^\\$(\\d+)/);\n if (capture) {\n result += match[Number(capture[1])] || \"\";\n index += capture[0].length;\n continue;\n }\n\n if (destination[index] === \"*\") {\n result += wildcardCaptures[wildcardIndex] || \"\";\n wildcardIndex += 1;\n index += 1;\n continue;\n }\n\n result += destination[index];\n index += 1;\n }\n\n return result;\n}\n","import type { FarmPlugin, FarmPluginContext } from \"../plugin\";\nimport type { RedirectConfig } from \"../config\";\nimport type { FarmRequest, FarmResponse } from \"../types\";\nimport type { ResolvedFarmI18nConfig } from \"../i18n/types\";\nimport { isFarmRedirectStatus } from \"../navigation-errors\";\nimport {\n compileConfigRoutePattern,\n interpolateConfigRouteDestination,\n localizeConfigRouteDestination,\n resolveConfigRoutePathname,\n} from \"./route-pattern\";\n\nexport function createRedirectsPlugin(\n redirects: RedirectConfig[],\n {\n beforeRequest: overrideBeforeRequest,\n afterResponse: overrideAfterResponse,\n i18n,\n }: {\n beforeRequest?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n afterResponse?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n i18n?: ResolvedFarmI18nConfig;\n } = {},\n): FarmPlugin {\n for (const redirect of redirects) {\n if (redirect.statusCode !== undefined && !isFarmRedirectStatus(redirect.statusCode)) {\n throw new RangeError(\n `Redirect \"${redirect.source}\" statusCode must be one of 301, 302, 303, 307, or 308.`,\n );\n }\n }\n const compiledRedirects = redirects.map((redirect) => ({\n redirect,\n pattern: compileConfigRoutePattern(redirect.source),\n }));\n\n return {\n name: \"farm:redirects\",\n enforce: \"pre\",\n async beforeRequest(req, res, context) {\n if (overrideBeforeRequest) {\n await overrideBeforeRequest(req, res, context);\n }\n const url = new URL(req.url || \"/\", `http://${req.headers.host}`);\n const routePath = resolveConfigRoutePathname(url.pathname, i18n);\n const pathname = routePath.pathname;\n\n for (const { redirect, pattern } of compiledRedirects) {\n const match = pathname.match(pattern.regex);\n if (match) {\n const destination = localizeConfigRouteDestination(\n interpolateConfigRouteDestination(redirect.destination, match, pattern.tokens),\n routePath.locale,\n i18n,\n );\n\n const statusCode = redirect.statusCode ?? (redirect.permanent ? 308 : 307);\n\n res.writeHead(statusCode, {\n Location: destination,\n });\n res.end();\n return;\n }\n }\n },\n\n async afterResponse(req, res, context) {\n if (overrideAfterResponse) {\n await overrideAfterResponse(req, res, context);\n }\n },\n };\n}\n","import type { FarmPlugin, FarmPluginContext } from \"../plugin\";\nimport type { HeaderConfig } from \"../config\";\nimport type { FarmRequest, FarmResponse } from \"../types\";\nimport type { ResolvedFarmI18nConfig } from \"../i18n/types\";\nimport { compileConfigRoutePattern, resolveConfigRoutePathname } from \"./route-pattern\";\n\nconst FARM_CONFIG_HEADERS_FINALIZER = Symbol.for(\"farm.configHeadersFinalizer\");\n\nfunction appendConfiguredLinkHeader(res: FarmResponse, value: string): void {\n const current = res.getHeader(\"Link\");\n if (current === undefined) {\n res.setHeader(\"Link\", value);\n return;\n }\n\n const currentValue = Array.isArray(current) ? current.join(\", \") : String(current);\n if (currentValue !== value && !currentValue.endsWith(`, ${value}`)) {\n res.setHeader(\"Link\", `${currentValue}, ${value}`);\n }\n}\n\nfunction applyResponseHeaders(\n res: FarmResponse,\n matchedHeaders: readonly HeaderConfig[\"headers\"][],\n): void {\n for (const headers of matchedHeaders) {\n for (const header of headers) {\n if (header.key.toLowerCase() === \"link\") {\n appendConfiguredLinkHeader(res, header.value);\n } else {\n res.setHeader(header.key, header.value);\n }\n }\n }\n}\n\nfunction applyWriteHeadHeaders(res: FarmResponse, headers: unknown): void {\n if (Array.isArray(headers)) {\n for (let index = 0; index + 1 < headers.length; index += 2) {\n res.setHeader(String(headers[index]), headers[index + 1]);\n }\n return;\n }\n\n if (!headers || typeof headers !== \"object\") return;\n for (const [key, value] of Object.entries(headers)) {\n if (value !== undefined) res.setHeader(key, value);\n }\n}\n\nexport function createHeadersPlugin(\n headers: HeaderConfig[],\n {\n beforeRequest: overrideBeforeRequest,\n afterResponse: overrideAfterResponse,\n i18n,\n }: {\n beforeRequest?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n afterResponse?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n i18n?: ResolvedFarmI18nConfig;\n } = {},\n): FarmPlugin {\n const compiledHeaders = headers.map((config) => ({\n config,\n pattern: compileConfigRoutePattern(config.source),\n }));\n\n return {\n name: \"farm:headers\",\n enforce: \"pre\",\n\n async beforeRequest(req, res, context) {\n if (overrideBeforeRequest) {\n await overrideBeforeRequest(req, res, context);\n }\n const url = new URL(req.url || \"/\", `http://${req.headers.host}`);\n const pathname = resolveConfigRoutePathname(url.pathname, i18n).pathname;\n const matchedHeaders = compiledHeaders\n .filter(({ pattern }) => pattern.regex.test(pathname))\n .map(({ config }) => config.headers);\n\n applyResponseHeaders(res, matchedHeaders);\n\n const responseWithFinalizer = res as FarmResponse & {\n [FARM_CONFIG_HEADERS_FINALIZER]?: boolean;\n };\n if (matchedHeaders.length === 0 || responseWithFinalizer[FARM_CONFIG_HEADERS_FINALIZER]) {\n return;\n }\n\n responseWithFinalizer[FARM_CONFIG_HEADERS_FINALIZER] = true;\n const writeHead = res.writeHead;\n res.writeHead = ((statusCode: number, ...args: unknown[]) => {\n const statusMessage = typeof args[0] === \"string\" ? (args.shift() as string) : undefined;\n applyWriteHeadHeaders(res, args[0]);\n applyResponseHeaders(res, matchedHeaders);\n return statusMessage === undefined\n ? (writeHead as any).call(res, statusCode)\n : (writeHead as any).call(res, statusCode, statusMessage);\n }) as FarmResponse[\"writeHead\"];\n },\n\n async afterResponse(req, res, context) {\n if (overrideAfterResponse) {\n await overrideAfterResponse(req, res, context);\n }\n },\n };\n}\n","import type { FarmPlugin, FarmPluginContext } from \"../plugin\";\nimport type { RewriteConfig } from \"../config\";\nimport type { FarmRequest, FarmResponse } from \"../types\";\nimport type { ResolvedFarmI18nConfig } from \"../i18n/types\";\nimport {\n compileConfigRoutePattern,\n interpolateConfigRouteDestination,\n localizeConfigRouteDestination,\n resolveConfigRoutePathname,\n} from \"./route-pattern\";\n\nexport const FARM_CONFIG_REWRITES_PLUGIN_NAME = \"farm:rewrites\";\n\nexport function createRewritesPlugin(\n rewrites: RewriteConfig[],\n {\n beforeRequest: overrideBeforeRequest,\n afterResponse: overrideAfterResponse,\n i18n,\n }: {\n beforeRequest?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n afterResponse?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n i18n?: ResolvedFarmI18nConfig;\n } = {},\n): FarmPlugin {\n const compiledRewrites = rewrites.map((rewrite) => ({\n rewrite,\n pattern: compileConfigRoutePattern(rewrite.source),\n }));\n\n return {\n name: FARM_CONFIG_REWRITES_PLUGIN_NAME,\n enforce: \"pre\",\n\n async beforeRequest(req, res, context) {\n if (overrideBeforeRequest) {\n await overrideBeforeRequest(req, res, context);\n }\n const url = new URL(req.url || \"/\", `http://${req.headers.host}`);\n const routePath = resolveConfigRoutePathname(url.pathname, i18n);\n const pathname = routePath.pathname;\n\n for (const { rewrite, pattern } of compiledRewrites) {\n const match = pathname.match(pattern.regex);\n if (match) {\n const newPath = localizeConfigRouteDestination(\n interpolateConfigRouteDestination(rewrite.destination, match, pattern.tokens),\n routePath.locale,\n i18n,\n );\n const destinationUrl = new URL(newPath, url);\n if (!destinationUrl.search && url.search) {\n destinationUrl.search = url.search;\n }\n req.url =\n destinationUrl.origin === url.origin\n ? destinationUrl.pathname + destinationUrl.search\n : destinationUrl.href;\n break;\n }\n }\n },\n\n async afterResponse(req, res, context) {\n if (overrideAfterResponse) {\n await overrideAfterResponse(req, res, context);\n }\n },\n };\n}\n","import type { FarmPlugin, FarmPluginContext } from \"../plugin\";\nimport type { FarmRequest, FarmResponse } from \"../types\";\n\nexport function createEnvPlugin(\n env: Record<string, string>,\n {\n beforeRequest: overrideBeforeRequest,\n afterResponse: overrideAfterResponse,\n }: {\n beforeRequest?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n afterResponse?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n } = {},\n): FarmPlugin {\n return {\n name: \"farm:env\",\n\n configResolved(config, context) {\n for (const [key, value] of Object.entries(env)) {\n process.env[key] = value;\n }\n },\n\n async beforeRequest(req, res, context) {\n if (overrideBeforeRequest) {\n await overrideBeforeRequest(req, res, context);\n }\n },\n\n async afterResponse(req, res, context) {\n if (overrideAfterResponse) {\n await overrideAfterResponse(req, res, context);\n }\n },\n };\n}\n","import type { FarmPlugin, FarmPluginContext } from \"../plugin\";\nimport type { FarmRequest, FarmResponse } from \"../types\";\nimport { Readable } from \"node:stream\";\nimport { constants, createBrotliCompress, createGzip } from \"node:zlib\";\n\ntype SupportedEncoding = \"br\" | \"gzip\";\n\nconst Q_VALUE = /^(?:0(?:\\.\\d{0,3})?|1(?:\\.0{0,3})?)$/;\n\nfunction parseEncodingQuality(header: string): Map<string, number> {\n const qualities = new Map<string, number>();\n\n for (const item of header.split(\",\")) {\n const [rawEncoding, ...parameters] = item.trim().split(\";\");\n const encoding = rawEncoding?.trim().toLowerCase();\n if (!encoding) continue;\n\n let quality = 1;\n for (const parameter of parameters) {\n const [rawName, rawValue] = parameter.split(\"=\", 2);\n if (rawName?.trim().toLowerCase() !== \"q\") continue;\n const value = rawValue?.trim() ?? \"\";\n quality = Q_VALUE.test(value) ? Number(value) : 0;\n }\n\n qualities.set(encoding, Math.max(qualities.get(encoding) ?? 0, quality));\n }\n\n return qualities;\n}\n\nfunction selectEncoding(header: string): SupportedEncoding | undefined {\n if (!header.trim()) return undefined;\n\n const qualities = parseEncodingQuality(header);\n const wildcard = qualities.get(\"*\") ?? 0;\n const quality = (encoding: SupportedEncoding) => qualities.get(encoding) ?? wildcard;\n const brotli = quality(\"br\");\n const gzip = quality(\"gzip\");\n\n if (brotli <= 0 && gzip <= 0) return undefined;\n return brotli >= gzip ? \"br\" : \"gzip\";\n}\n\nfunction isCompressionEligible(request: Request, response: Response): boolean {\n if (\n (request.method !== \"HEAD\" && !response.body) ||\n response.status === 204 ||\n response.status === 205 ||\n response.status === 304 ||\n response.headers.has(\"content-encoding\") ||\n response.headers.has(\"content-range\") ||\n response.headers.get(\"cache-control\")?.toLowerCase().includes(\"no-transform\")\n ) {\n return false;\n }\n\n const contentType = response.headers.get(\"content-type\")?.toLowerCase() ?? \"\";\n return contentType !== \"text/event-stream\";\n}\n\nfunction appendVary(headers: Headers, value: string): void {\n const current = headers.get(\"vary\");\n const values = current\n ? current\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean)\n : [];\n if (values.includes(\"*\")) return;\n if (!values.some((item) => item.toLowerCase() === value.toLowerCase())) {\n values.push(value);\n }\n headers.set(\"vary\", values.join(\", \"));\n}\n\nfunction compressResponse(response: Response, encoding: SupportedEncoding): Response {\n const compressor =\n encoding === \"br\" ? createBrotliCompress() : createGzip({ flush: constants.Z_SYNC_FLUSH });\n const input = Readable.fromWeb(response.body as any);\n const output = input.pipe(compressor);\n const headers = new Headers(response.headers);\n\n headers.set(\"content-encoding\", encoding);\n headers.delete(\"content-length\");\n appendVary(headers, \"Accept-Encoding\");\n\n const etag = headers.get(\"etag\");\n if (etag && !etag.startsWith(\"W/\")) {\n headers.set(\"etag\", `W/${etag}`);\n }\n\n return new Response(Readable.toWeb(output) as ReadableStream<Uint8Array>, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n\nfunction varyIdentityResponse(response: Response): Response {\n const headers = new Headers(response.headers);\n appendVary(headers, \"Accept-Encoding\");\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n\nexport function createCompressionPlugin({\n beforeRequest: overrideBeforeRequest,\n afterResponse: overrideAfterResponse,\n}: {\n beforeRequest?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n afterResponse?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n} = {}): FarmPlugin {\n return {\n name: \"farm:compression\",\n enforce: \"post\",\n\n runtime: {\n after({ request, response, isProd }) {\n if (!isProd || !isCompressionEligible(request, response)) return;\n\n if (request.method === \"HEAD\") return varyIdentityResponse(response);\n\n const encoding = selectEncoding(request.headers.get(\"accept-encoding\") ?? \"\");\n if (!encoding) return varyIdentityResponse(response);\n return compressResponse(response, encoding);\n },\n },\n\n async beforeRequest(req, res, context) {\n if (overrideBeforeRequest) {\n await overrideBeforeRequest(req, res, context);\n }\n },\n\n async afterResponse(req, res, context) {\n if (overrideAfterResponse) {\n await overrideAfterResponse(req, res, context);\n }\n },\n };\n}\n","import type { FarmPlugin, FarmPluginContext } from \"../plugin\";\nimport type { FarmResponse } from \"../types\";\nimport type { FarmRequest } from \"../types\";\n\nexport function createLoggerPlugin({\n beforeRequest,\n afterResponse,\n}: {\n beforeRequest?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n afterResponse?: (\n req: FarmRequest,\n res: FarmResponse,\n context: FarmPluginContext,\n ) => void | Promise<void>;\n} = {}): FarmPlugin {\n const plugin: FarmPlugin = {\n name: \"farm:logger\",\n enforce: \"post\",\n };\n\n if (beforeRequest) {\n plugin.beforeRequest = async (req, res, context) => {\n await beforeRequest(req, res, context);\n };\n }\n if (afterResponse) {\n plugin.afterResponse = async (req, res, context) => {\n await afterResponse(req, res, context);\n };\n }\n\n return plugin;\n}\n"],"mappings":"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","names":[]}
|
package/dist/server-plugins.mjs
CHANGED
package/dist/server.cjs
CHANGED
|
@@ -18702,6 +18702,25 @@ var fs4 = __toESM(require("fs"));
|
|
|
18702
18702
|
var path12 = __toESM(require("path"));
|
|
18703
18703
|
init_utils();
|
|
18704
18704
|
|
|
18705
|
+
// src/server/dev-styles.ts
|
|
18706
|
+
var STYLE_EXTENSIONS = /\.(css|scss|sass|less|styl|stylus)(?:$|\?)/;
|
|
18707
|
+
var ALREADY_LINKED = "/src/app/globals.css";
|
|
18708
|
+
function collectDevStylesheetUrls(modules) {
|
|
18709
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18710
|
+
for (const mod of modules) {
|
|
18711
|
+
const id = mod.id ?? mod.file ?? "";
|
|
18712
|
+
if (!STYLE_EXTENSIONS.test(id)) continue;
|
|
18713
|
+
if (id.includes(".module.")) continue;
|
|
18714
|
+
const url = mod.url;
|
|
18715
|
+
if (!url || !url.startsWith("/")) continue;
|
|
18716
|
+
const bare = url.split("?")[0];
|
|
18717
|
+
if (bare === ALREADY_LINKED) continue;
|
|
18718
|
+
seen.add(bare);
|
|
18719
|
+
}
|
|
18720
|
+
return [...seen].sort();
|
|
18721
|
+
}
|
|
18722
|
+
__name(collectDevStylesheetUrls, "collectDevStylesheetUrls");
|
|
18723
|
+
|
|
18705
18724
|
// src/server/full-document.ts
|
|
18706
18725
|
function stripContentsWrappers(markup) {
|
|
18707
18726
|
let out = markup.replace(/^\s+/, "");
|
|
@@ -22177,7 +22196,7 @@ _setFarmThemeServerSnapshotResolver(() => {
|
|
|
22177
22196
|
});
|
|
22178
22197
|
|
|
22179
22198
|
// package.json
|
|
22180
|
-
var version = "0.1.0-beta.
|
|
22199
|
+
var version = "0.1.0-beta.76";
|
|
22181
22200
|
|
|
22182
22201
|
// src/version.ts
|
|
22183
22202
|
var FARM_VERSION = version;
|
|
@@ -22548,6 +22567,18 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
22548
22567
|
pageElement
|
|
22549
22568
|
);
|
|
22550
22569
|
}
|
|
22570
|
+
/// Stylesheets the app imported through JS (fontsource packages, component
|
|
22571
|
+
/// CSS) that the document must link alongside globals.css — see #658.
|
|
22572
|
+
collectDevStyleHrefs() {
|
|
22573
|
+
const graph = this.viteServer?.moduleGraph;
|
|
22574
|
+
if (!graph) return [];
|
|
22575
|
+
return collectDevStylesheetUrls(graph.idToModuleMap.values());
|
|
22576
|
+
}
|
|
22577
|
+
collectDevStyleLinks() {
|
|
22578
|
+
return this.collectDevStyleHrefs().map(
|
|
22579
|
+
(href) => `<link rel="stylesheet" href="${escapeHtmlAttribute2(href)}">`
|
|
22580
|
+
);
|
|
22581
|
+
}
|
|
22551
22582
|
createLayoutBoundary(pattern, layoutElement) {
|
|
22552
22583
|
return this.rendererRuntime.createElement(
|
|
22553
22584
|
"div",
|
|
@@ -23762,7 +23793,11 @@ var _ServerRenderer = class _ServerRenderer {
|
|
|
23762
23793
|
{
|
|
23763
23794
|
tag: "link",
|
|
23764
23795
|
attrs: { rel: "stylesheet", href: "/src/app/globals.css" }
|
|
23765
|
-
}
|
|
23796
|
+
},
|
|
23797
|
+
...this.collectDevStyleHrefs().map((href) => ({
|
|
23798
|
+
tag: "link",
|
|
23799
|
+
attrs: { rel: "stylesheet", href }
|
|
23800
|
+
}))
|
|
23766
23801
|
]
|
|
23767
23802
|
};
|
|
23768
23803
|
for (const routeEntry of manifest.routes) {
|
|
@@ -23858,6 +23893,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
|
|
|
23858
23893
|
rendererHead,
|
|
23859
23894
|
renderFarmFontDevHead(this.config.root || process.cwd()),
|
|
23860
23895
|
`<link rel="stylesheet" href="/src/app/globals.css">`,
|
|
23896
|
+
...this.collectDevStyleLinks(),
|
|
23861
23897
|
`<script type="module" src="/@vite/client"></script>`,
|
|
23862
23898
|
rendererHydrationScript,
|
|
23863
23899
|
bootstrapScript
|
|
@@ -23876,7 +23912,8 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
|
|
|
23876
23912
|
${documentTitleTag}${metaTags}${alternateTags}${rendererHead ? `
|
|
23877
23913
|
${rendererHead}` : ""}
|
|
23878
23914
|
${renderFarmFontDevHead(this.config.root || process.cwd())}
|
|
23879
|
-
<link rel="stylesheet" href="/src/app/globals.css"
|
|
23915
|
+
<link rel="stylesheet" href="/src/app/globals.css">${this.collectDevStyleLinks().map((l) => `
|
|
23916
|
+
${l}`).join("")}
|
|
23880
23917
|
<script type="module" src="/@vite/client"></script>
|
|
23881
23918
|
${rendererHydrationScript}
|
|
23882
23919
|
${bootstrapScript}
|
|
@@ -23941,7 +23978,11 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
|
|
|
23941
23978
|
{
|
|
23942
23979
|
tag: "link",
|
|
23943
23980
|
attrs: { rel: "stylesheet", href: "/src/app/globals.css" }
|
|
23944
|
-
}
|
|
23981
|
+
},
|
|
23982
|
+
...this.collectDevStyleHrefs().map((href) => ({
|
|
23983
|
+
tag: "link",
|
|
23984
|
+
attrs: { rel: "stylesheet", href }
|
|
23985
|
+
}))
|
|
23945
23986
|
]
|
|
23946
23987
|
};
|
|
23947
23988
|
for (const routeEntry of manifest.routes) {
|
|
@@ -24028,6 +24069,7 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
|
|
|
24028
24069
|
{ style: { display: "contents" } },
|
|
24029
24070
|
element
|
|
24030
24071
|
);
|
|
24072
|
+
const devStyleLinks = this.collectDevStyleLinks();
|
|
24031
24073
|
const { pipe } = renderToPipeableStream2(streamRoot, {
|
|
24032
24074
|
onShellReady() {
|
|
24033
24075
|
const shellReadyMs = Date.now() - streamStartTime;
|
|
@@ -24049,7 +24091,8 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(
|
|
|
24049
24091
|
${hasFavicon ? "" : '<link rel="icon" href="data:,">'}
|
|
24050
24092
|
<title>${title}</title>${metaTags}${i18nAlternateTags}
|
|
24051
24093
|
${fontHead}
|
|
24052
|
-
<link rel="stylesheet" href="/src/app/globals.css"
|
|
24094
|
+
<link rel="stylesheet" href="/src/app/globals.css" />${devStyleLinks.map((l) => `
|
|
24095
|
+
${l}`).join("")}
|
|
24053
24096
|
<script type="module" src="/@vite/client"></script>
|
|
24054
24097
|
${propsScript}
|
|
24055
24098
|
${hydrationClickQueueScript}
|
|
@@ -24276,6 +24319,7 @@ ${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue2(i18nSnapshot)};
|
|
|
24276
24319
|
alternateLinks,
|
|
24277
24320
|
fontHead,
|
|
24278
24321
|
`<link rel="stylesheet" href="/src/app/globals.css" />`,
|
|
24322
|
+
...this.collectDevStyleLinks(),
|
|
24279
24323
|
`<script type="module" src="/@vite/client"></script>`,
|
|
24280
24324
|
rendererHydrationScript,
|
|
24281
24325
|
integrationManifestScript
|
|
@@ -24293,7 +24337,8 @@ ${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue2(i18nSnapshot)};
|
|
|
24293
24337
|
<link rel="icon" href="data:,">
|
|
24294
24338
|
<title>${escapeHtmlAttribute2(documentTitle)}</title>${alternateLinks}
|
|
24295
24339
|
${fontHead}
|
|
24296
|
-
<link rel="stylesheet" href="/src/app/globals.css"
|
|
24340
|
+
<link rel="stylesheet" href="/src/app/globals.css" />${this.collectDevStyleLinks().map((l) => `
|
|
24341
|
+
${l}`).join("")}
|
|
24297
24342
|
<script type="module" src="/@vite/client"></script>
|
|
24298
24343
|
${rendererHydrationScript}
|
|
24299
24344
|
${integrationManifestScript}
|
|
@@ -33510,17 +33555,18 @@ function selectEncoding(header) {
|
|
|
33510
33555
|
return brotli >= gzip ? "br" : "gzip";
|
|
33511
33556
|
}
|
|
33512
33557
|
__name(selectEncoding, "selectEncoding");
|
|
33513
|
-
function
|
|
33514
|
-
if (request.method
|
|
33558
|
+
function isCompressionEligible(request, response) {
|
|
33559
|
+
if (request.method !== "HEAD" && !response.body || response.status === 204 || response.status === 205 || response.status === 304 || response.headers.has("content-encoding") || response.headers.has("content-range") || response.headers.get("cache-control")?.toLowerCase().includes("no-transform")) {
|
|
33515
33560
|
return false;
|
|
33516
33561
|
}
|
|
33517
33562
|
const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
|
|
33518
33563
|
return contentType !== "text/event-stream";
|
|
33519
33564
|
}
|
|
33520
|
-
__name(
|
|
33565
|
+
__name(isCompressionEligible, "isCompressionEligible");
|
|
33521
33566
|
function appendVary(headers, value) {
|
|
33522
33567
|
const current = headers.get("vary");
|
|
33523
33568
|
const values = current ? current.split(",").map((item) => item.trim()).filter(Boolean) : [];
|
|
33569
|
+
if (values.includes("*")) return;
|
|
33524
33570
|
if (!values.some((item) => item.toLowerCase() === value.toLowerCase())) {
|
|
33525
33571
|
values.push(value);
|
|
33526
33572
|
}
|
|
@@ -33546,6 +33592,16 @@ function compressResponse(response, encoding) {
|
|
|
33546
33592
|
});
|
|
33547
33593
|
}
|
|
33548
33594
|
__name(compressResponse, "compressResponse");
|
|
33595
|
+
function varyIdentityResponse(response) {
|
|
33596
|
+
const headers = new Headers(response.headers);
|
|
33597
|
+
appendVary(headers, "Accept-Encoding");
|
|
33598
|
+
return new Response(response.body, {
|
|
33599
|
+
status: response.status,
|
|
33600
|
+
statusText: response.statusText,
|
|
33601
|
+
headers
|
|
33602
|
+
});
|
|
33603
|
+
}
|
|
33604
|
+
__name(varyIdentityResponse, "varyIdentityResponse");
|
|
33549
33605
|
function createCompressionPlugin({
|
|
33550
33606
|
beforeRequest: overrideBeforeRequest,
|
|
33551
33607
|
afterResponse: overrideAfterResponse
|
|
@@ -33555,9 +33611,10 @@ function createCompressionPlugin({
|
|
|
33555
33611
|
enforce: "post",
|
|
33556
33612
|
runtime: {
|
|
33557
33613
|
after({ request, response, isProd }) {
|
|
33558
|
-
if (!isProd || !
|
|
33614
|
+
if (!isProd || !isCompressionEligible(request, response)) return;
|
|
33615
|
+
if (request.method === "HEAD") return varyIdentityResponse(response);
|
|
33559
33616
|
const encoding = selectEncoding(request.headers.get("accept-encoding") ?? "");
|
|
33560
|
-
if (!encoding) return;
|
|
33617
|
+
if (!encoding) return varyIdentityResponse(response);
|
|
33561
33618
|
return compressResponse(response, encoding);
|
|
33562
33619
|
}
|
|
33563
33620
|
},
|