Add first business article and article layout
This commit is contained in:
29
node_modules/astro/dist/core/cache/config.d.ts
generated
vendored
Normal file
29
node_modules/astro/dist/core/cache/config.d.ts
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
import * as z from 'zod/v4';
|
||||
/**
|
||||
* Cache provider configuration (experimental.cache).
|
||||
* Provider only - routes are configured via experimental.routeRules.
|
||||
*/
|
||||
export declare const CacheSchema: z.ZodObject<{
|
||||
provider: z.ZodOptional<z.ZodObject<{
|
||||
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
||||
entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
|
||||
name: z.ZodOptional<z.ZodString>;
|
||||
}, z.core.$strip>>;
|
||||
}, z.core.$strip>;
|
||||
/**
|
||||
* Route rules configuration (experimental.routeRules).
|
||||
* Maps glob patterns to route rules.
|
||||
*
|
||||
* Example:
|
||||
* ```ts
|
||||
* routeRules: {
|
||||
* '/api/*': { swr: 600 },
|
||||
* '/products/*': { maxAge: 3600, tags: ['products'] },
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export declare const RouteRulesSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
||||
maxAge: z.ZodOptional<z.ZodNumber>;
|
||||
swr: z.ZodOptional<z.ZodNumber>;
|
||||
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
||||
}, z.core.$strip>>;
|
||||
20
node_modules/astro/dist/core/cache/config.js
generated
vendored
Normal file
20
node_modules/astro/dist/core/cache/config.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import * as z from "zod/v4";
|
||||
const CacheProviderConfigSchema = z.object({
|
||||
config: z.record(z.string(), z.any()).optional(),
|
||||
entrypoint: z.union([z.string(), z.instanceof(URL)]),
|
||||
name: z.string().optional()
|
||||
});
|
||||
const CacheOptionsSchema = z.object({
|
||||
maxAge: z.number().int().min(0).optional(),
|
||||
swr: z.number().int().min(0).optional(),
|
||||
tags: z.array(z.string()).optional()
|
||||
});
|
||||
const CacheSchema = z.object({
|
||||
provider: CacheProviderConfigSchema.optional()
|
||||
});
|
||||
const RouteRuleSchema = CacheOptionsSchema;
|
||||
const RouteRulesSchema = z.record(z.string(), RouteRuleSchema);
|
||||
export {
|
||||
CacheSchema,
|
||||
RouteRulesSchema
|
||||
};
|
||||
56
node_modules/astro/dist/core/cache/memory-provider.d.ts
generated
vendored
Normal file
56
node_modules/astro/dist/core/cache/memory-provider.d.ts
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { CacheProvider } from './types.js';
|
||||
export interface MemoryCacheQueryOptions {
|
||||
/**
|
||||
* Sort query parameters alphabetically so that parameter order does not
|
||||
* affect the cache key. Enabled by default.
|
||||
* @default true
|
||||
*/
|
||||
sort?: boolean;
|
||||
/**
|
||||
* Only include these query parameter names in the cache key.
|
||||
* All other parameters are ignored, including the default tracking
|
||||
* parameter exclusions. Cannot be used together with `exclude`.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* memoryCache({ query: { include: ['page', 'sort', 'q'] } })
|
||||
* ```
|
||||
*/
|
||||
include?: string[];
|
||||
/**
|
||||
* Exclude query parameters whose names match these patterns from the cache
|
||||
* key. Supports glob wildcards (e.g. `"utm_*"`). Cannot be used together
|
||||
* with `include`.
|
||||
*
|
||||
* By default, common tracking and analytics parameters (`utm_*`, `fbclid`,
|
||||
* `gclid`, etc.) are excluded. Set to `[]` to include all query parameters
|
||||
* in the cache key.
|
||||
*
|
||||
* @default ['utm_*', 'fbclid', 'gclid', 'gbraid', 'wbraid', 'dclid', 'msclkid', 'twclid', 'li_fat_id', 'mc_cid', 'mc_eid', '_ga', '_gl', '_hsenc', '_hsmi', '_ke', 'oly_anon_id', 'oly_enc_id', 'rb_clickid', 's_cid', 'vero_id', 'wickedid', 'yclid', '__s', 'ref']
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* // Only exclude specific params (replaces defaults)
|
||||
* memoryCache({ query: { exclude: ['session_id', 'token'] } })
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* // Include all query parameters (disable default exclusions)
|
||||
* memoryCache({ query: { exclude: [] } })
|
||||
* ```
|
||||
*/
|
||||
exclude?: string[];
|
||||
}
|
||||
export interface MemoryCacheProviderOptions {
|
||||
/** Maximum number of entries to keep in cache. Defaults to 1000. */
|
||||
max?: number;
|
||||
/**
|
||||
* Query parameter handling for cache keys.
|
||||
* By default, parameters are sorted alphabetically so that order does not
|
||||
* affect the cache key.
|
||||
*/
|
||||
query?: MemoryCacheQueryOptions;
|
||||
}
|
||||
declare const memoryProvider: (config: MemoryCacheProviderOptions | undefined) => CacheProvider;
|
||||
export default memoryProvider;
|
||||
305
node_modules/astro/dist/core/cache/memory-provider.js
generated
vendored
Normal file
305
node_modules/astro/dist/core/cache/memory-provider.js
generated
vendored
Normal file
@@ -0,0 +1,305 @@
|
||||
import picomatch from "picomatch";
|
||||
import { AstroError } from "../errors/errors.js";
|
||||
import { CacheQueryConfigConflict } from "../errors/errors-data.js";
|
||||
function parseCdnCacheControl(header) {
|
||||
let maxAge = 0;
|
||||
let swr = 0;
|
||||
if (!header) return { maxAge, swr };
|
||||
for (const part of header.split(",")) {
|
||||
const trimmed = part.trim().toLowerCase();
|
||||
if (trimmed.startsWith("max-age=")) {
|
||||
maxAge = Number.parseInt(trimmed.slice(8), 10) || 0;
|
||||
} else if (trimmed.startsWith("stale-while-revalidate=")) {
|
||||
swr = Number.parseInt(trimmed.slice(23), 10) || 0;
|
||||
}
|
||||
}
|
||||
return { maxAge, swr };
|
||||
}
|
||||
function parseCacheTags(header) {
|
||||
if (!header) return [];
|
||||
return header.split(",").map((t) => t.trim()).filter(Boolean);
|
||||
}
|
||||
const DEFAULT_EXCLUDED_PARAMS = [
|
||||
"utm_*",
|
||||
"fbclid",
|
||||
"gclid",
|
||||
"gbraid",
|
||||
"wbraid",
|
||||
"dclid",
|
||||
"msclkid",
|
||||
"twclid",
|
||||
"li_fat_id",
|
||||
"mc_cid",
|
||||
"mc_eid",
|
||||
"_ga",
|
||||
"_gl",
|
||||
"_hsenc",
|
||||
"_hsmi",
|
||||
"_ke",
|
||||
"oly_anon_id",
|
||||
"oly_enc_id",
|
||||
"rb_clickid",
|
||||
"s_cid",
|
||||
"vero_id",
|
||||
"wickedid",
|
||||
"yclid",
|
||||
"__s",
|
||||
"ref"
|
||||
];
|
||||
function normalizeQueryConfig(query) {
|
||||
if (query?.include && query?.exclude) {
|
||||
throw new AstroError(CacheQueryConfigConflict);
|
||||
}
|
||||
const sort = query?.sort !== false;
|
||||
const include = query?.include ?? null;
|
||||
const excludePatterns = include ? [] : query?.exclude ?? DEFAULT_EXCLUDED_PARAMS;
|
||||
const excludeMatcher = excludePatterns.length > 0 ? picomatch(excludePatterns, { nocase: true }) : null;
|
||||
return { sort, include, excludeMatcher };
|
||||
}
|
||||
function buildQueryString(url, config) {
|
||||
const params = new URLSearchParams(url.searchParams);
|
||||
if (config.include) {
|
||||
const allowed = new Set(config.include);
|
||||
for (const key of [...params.keys()]) {
|
||||
if (!allowed.has(key)) {
|
||||
params.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (config.excludeMatcher) {
|
||||
for (const key of [...params.keys()]) {
|
||||
if (config.excludeMatcher(key)) {
|
||||
params.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (config.sort) {
|
||||
params.sort();
|
||||
}
|
||||
const qs = params.toString();
|
||||
return qs ? `?${qs}` : "";
|
||||
}
|
||||
function getCacheKey(url, queryConfig) {
|
||||
return `${url.origin}${url.pathname}${buildQueryString(url, queryConfig)}`;
|
||||
}
|
||||
function getPathFromCacheKey(key, queryConfig) {
|
||||
const urlPart = key.split("\0")[0];
|
||||
if (!URL.canParse(urlPart)) return null;
|
||||
const url = new URL(urlPart);
|
||||
return `${url.pathname}${buildQueryString(url, queryConfig)}`;
|
||||
}
|
||||
const IGNORED_VARY_HEADERS = /* @__PURE__ */ new Set(["cookie", "set-cookie"]);
|
||||
function parseVaryHeader(response) {
|
||||
const vary = response.headers.get("Vary");
|
||||
if (!vary || vary.trim() === "*") return void 0;
|
||||
const headers = vary.split(",").map((h) => h.trim().toLowerCase()).filter((h) => h && !IGNORED_VARY_HEADERS.has(h));
|
||||
return headers.length > 0 ? headers : void 0;
|
||||
}
|
||||
function getVaryValues(request, varyHeaders) {
|
||||
const values = /* @__PURE__ */ Object.create(null);
|
||||
for (const header of varyHeaders) {
|
||||
values[header] = request.headers.get(header) ?? "";
|
||||
}
|
||||
return values;
|
||||
}
|
||||
function matchesVary(request, entry) {
|
||||
if (!entry.vary || !entry.varyValues) return true;
|
||||
for (const header of entry.vary) {
|
||||
const requestValue = request.headers.get(header) ?? "";
|
||||
if (requestValue !== entry.varyValues[header]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function hasSetCookieHeader(response) {
|
||||
return response.headers.has("set-cookie");
|
||||
}
|
||||
function warnSkippedSetCookie(url) {
|
||||
console.warn(
|
||||
`[astro:cache] Skipping cache for ${url.pathname}${url.search} because response includes Set-Cookie.`
|
||||
);
|
||||
}
|
||||
class LRUMap {
|
||||
#map = /* @__PURE__ */ new Map();
|
||||
#max;
|
||||
constructor(max) {
|
||||
this.#max = max;
|
||||
}
|
||||
get(key) {
|
||||
const value = this.#map.get(key);
|
||||
if (value !== void 0) {
|
||||
this.#map.delete(key);
|
||||
this.#map.set(key, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
set(key, value) {
|
||||
if (this.#map.has(key)) {
|
||||
this.#map.delete(key);
|
||||
} else if (this.#map.size >= this.#max) {
|
||||
const oldest = this.#map.keys().next().value;
|
||||
this.#map.delete(oldest);
|
||||
}
|
||||
this.#map.set(key, value);
|
||||
}
|
||||
delete(key) {
|
||||
return this.#map.delete(key);
|
||||
}
|
||||
values() {
|
||||
return this.#map.values();
|
||||
}
|
||||
keys() {
|
||||
return this.#map.keys();
|
||||
}
|
||||
get size() {
|
||||
return this.#map.size;
|
||||
}
|
||||
}
|
||||
async function serializeResponse(response, request, maxAge, swr, tags) {
|
||||
const body = await response.arrayBuffer();
|
||||
const headers = [];
|
||||
response.headers.forEach((value, key) => {
|
||||
if (key.toLowerCase() === "set-cookie") return;
|
||||
headers.push([key, value]);
|
||||
});
|
||||
const vary = parseVaryHeader(response);
|
||||
return {
|
||||
body,
|
||||
status: response.status,
|
||||
headers,
|
||||
storedAt: Date.now(),
|
||||
maxAge,
|
||||
swr,
|
||||
tags,
|
||||
vary,
|
||||
varyValues: vary ? getVaryValues(request, vary) : void 0
|
||||
};
|
||||
}
|
||||
function createResponseFromCacheEntry(entry) {
|
||||
const headers = new Headers(entry.headers);
|
||||
return new Response(entry.body.slice(0), {
|
||||
status: entry.status,
|
||||
headers
|
||||
});
|
||||
}
|
||||
function isExpired(entry) {
|
||||
const age = (Date.now() - entry.storedAt) / 1e3;
|
||||
return age > entry.maxAge;
|
||||
}
|
||||
function isStale(entry) {
|
||||
const age = (Date.now() - entry.storedAt) / 1e3;
|
||||
return age > entry.maxAge && age <= entry.maxAge + entry.swr;
|
||||
}
|
||||
function buildVarySuffix(request, varyHeaders) {
|
||||
if (varyHeaders.length === 0) return "";
|
||||
const parts = [];
|
||||
for (const header of varyHeaders) {
|
||||
parts.push(`${header}=${request.headers.get(header) ?? ""}`);
|
||||
}
|
||||
return `\0${parts.join("\0")}`;
|
||||
}
|
||||
const memoryProvider = ((config) => {
|
||||
const max = config?.max ?? 1e3;
|
||||
const queryConfig = normalizeQueryConfig(config?.query);
|
||||
const cache = new LRUMap(max);
|
||||
const varyMap = /* @__PURE__ */ new Map();
|
||||
return {
|
||||
name: "memory",
|
||||
async onRequest(context, next) {
|
||||
const requestUrl = new URL(context.request.url);
|
||||
if (context.request.method !== "GET") {
|
||||
return next();
|
||||
}
|
||||
const primaryKey = getCacheKey(requestUrl, queryConfig);
|
||||
const knownVary = varyMap.get(primaryKey);
|
||||
const varySuffix = knownVary ? buildVarySuffix(context.request, knownVary) : "";
|
||||
const key = primaryKey + varySuffix;
|
||||
const cached = cache.get(key);
|
||||
if (cached) {
|
||||
if (matchesVary(context.request, cached)) {
|
||||
if (!isExpired(cached)) {
|
||||
const response2 = createResponseFromCacheEntry(cached);
|
||||
response2.headers.set("X-Astro-Cache", "HIT");
|
||||
return response2;
|
||||
}
|
||||
if (isStale(cached)) {
|
||||
next().then(async (freshResponse) => {
|
||||
const cdnCC2 = freshResponse.headers.get("CDN-Cache-Control");
|
||||
const { maxAge: newMaxAge, swr: newSwr } = parseCdnCacheControl(cdnCC2);
|
||||
if (newMaxAge > 0) {
|
||||
if (hasSetCookieHeader(freshResponse)) {
|
||||
warnSkippedSetCookie(requestUrl);
|
||||
return;
|
||||
}
|
||||
const newTags = parseCacheTags(freshResponse.headers.get("Cache-Tag"));
|
||||
const newEntry = await serializeResponse(
|
||||
freshResponse,
|
||||
context.request,
|
||||
newMaxAge,
|
||||
newSwr,
|
||||
newTags
|
||||
);
|
||||
if (newEntry.vary) {
|
||||
varyMap.set(primaryKey, newEntry.vary);
|
||||
}
|
||||
cache.set(key, newEntry);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.warn(
|
||||
`[astro:cache] Background revalidation failed for ${requestUrl.pathname}${requestUrl.search}: ${String(
|
||||
error
|
||||
)}`
|
||||
);
|
||||
});
|
||||
const response2 = createResponseFromCacheEntry(cached);
|
||||
response2.headers.set("X-Astro-Cache", "STALE");
|
||||
return response2;
|
||||
}
|
||||
}
|
||||
}
|
||||
const response = await next();
|
||||
const cdnCC = response.headers.get("CDN-Cache-Control");
|
||||
const { maxAge, swr } = parseCdnCacheControl(cdnCC);
|
||||
if (maxAge > 0) {
|
||||
if (hasSetCookieHeader(response)) {
|
||||
warnSkippedSetCookie(requestUrl);
|
||||
return response;
|
||||
}
|
||||
const tags = parseCacheTags(response.headers.get("Cache-Tag"));
|
||||
const [forCache, forClient] = [response.clone(), response];
|
||||
const entry = await serializeResponse(forCache, context.request, maxAge, swr, tags);
|
||||
let storeKey = primaryKey;
|
||||
if (entry.vary) {
|
||||
varyMap.set(primaryKey, entry.vary);
|
||||
storeKey = primaryKey + buildVarySuffix(context.request, entry.vary);
|
||||
}
|
||||
cache.set(storeKey, entry);
|
||||
forClient.headers.set("X-Astro-Cache", "MISS");
|
||||
return forClient;
|
||||
}
|
||||
return response;
|
||||
},
|
||||
async invalidate(invalidateOptions) {
|
||||
if (invalidateOptions.path) {
|
||||
for (const key of [...cache.keys()]) {
|
||||
if (getPathFromCacheKey(key, queryConfig) === invalidateOptions.path) {
|
||||
cache.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (invalidateOptions.tags) {
|
||||
const tagsToInvalidate = Array.isArray(invalidateOptions.tags) ? invalidateOptions.tags : [invalidateOptions.tags];
|
||||
const tagsSet = new Set(tagsToInvalidate);
|
||||
for (const key of [...cache.keys()]) {
|
||||
const entry = cache.get(key);
|
||||
if (entry && entry.tags.some((t) => tagsSet.has(t))) {
|
||||
cache.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
var memory_provider_default = memoryProvider;
|
||||
export {
|
||||
memory_provider_default as default
|
||||
};
|
||||
42
node_modules/astro/dist/core/cache/runtime/cache.d.ts
generated
vendored
Normal file
42
node_modules/astro/dist/core/cache/runtime/cache.d.ts
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
import type { CacheHint, CacheOptions, CacheProvider, InvalidateOptions, LiveDataEntry } from '../types.js';
|
||||
export interface CacheLike {
|
||||
/**
|
||||
* Whether caching is enabled. `false` when no cache provider is configured
|
||||
* or in dev mode. Libraries can check this before calling cache methods.
|
||||
*/
|
||||
readonly enabled: boolean;
|
||||
/**
|
||||
* Set cache options for the current request. Call multiple times to merge options.
|
||||
* Pass `false` to explicitly opt out of caching.
|
||||
*/
|
||||
set(input: CacheOptions | CacheHint | LiveDataEntry | false): void;
|
||||
/** All accumulated cache tags for this request. */
|
||||
readonly tags: string[];
|
||||
/** A read-only snapshot of the current cache options, including accumulated tags. */
|
||||
readonly options: Readonly<CacheOptions>;
|
||||
/**
|
||||
* Purge cached entries by tag or path. Requires a cache provider to be configured.
|
||||
*/
|
||||
invalidate(input: InvalidateOptions | LiveDataEntry): Promise<void>;
|
||||
}
|
||||
export declare class AstroCache implements CacheLike {
|
||||
#private;
|
||||
readonly enabled = true;
|
||||
constructor(provider: CacheProvider | null);
|
||||
set(input: CacheOptions | CacheHint | LiveDataEntry | false): void;
|
||||
get tags(): string[];
|
||||
/**
|
||||
* Get the current cache options (read-only snapshot).
|
||||
* Includes all accumulated options: maxAge, swr, tags, etag, lastModified.
|
||||
*/
|
||||
get options(): Readonly<CacheOptions>;
|
||||
invalidate(input: InvalidateOptions | LiveDataEntry): Promise<void>;
|
||||
}
|
||||
/**
|
||||
* Apply cache headers to a response.
|
||||
*/
|
||||
export declare function applyCacheHeaders(cache: CacheLike, response: Response): void;
|
||||
/**
|
||||
* Check whether the cache has any active state worth acting on.
|
||||
*/
|
||||
export declare function isCacheActive(cache: CacheLike): boolean;
|
||||
99
node_modules/astro/dist/core/cache/runtime/cache.js
generated
vendored
Normal file
99
node_modules/astro/dist/core/cache/runtime/cache.js
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
import { AstroError } from "../../errors/errors.js";
|
||||
import { CacheNotEnabled } from "../../errors/errors-data.js";
|
||||
import { defaultSetHeaders, isLiveDataEntry } from "./utils.js";
|
||||
const APPLY_HEADERS = /* @__PURE__ */ Symbol.for("astro:cache:apply");
|
||||
const IS_ACTIVE = /* @__PURE__ */ Symbol.for("astro:cache:active");
|
||||
class AstroCache {
|
||||
#options = {};
|
||||
#tags = /* @__PURE__ */ new Set();
|
||||
#disabled = false;
|
||||
#provider;
|
||||
enabled = true;
|
||||
constructor(provider) {
|
||||
this.#provider = provider;
|
||||
}
|
||||
set(input) {
|
||||
if (input === false) {
|
||||
this.#disabled = true;
|
||||
this.#tags.clear();
|
||||
this.#options = {};
|
||||
return;
|
||||
}
|
||||
this.#disabled = false;
|
||||
let options;
|
||||
if (isLiveDataEntry(input)) {
|
||||
if (!input.cacheHint) return;
|
||||
options = input.cacheHint;
|
||||
} else {
|
||||
options = input;
|
||||
}
|
||||
if ("maxAge" in options && options.maxAge !== void 0) this.#options.maxAge = options.maxAge;
|
||||
if ("swr" in options && options.swr !== void 0)
|
||||
this.#options.swr = options.swr;
|
||||
if ("etag" in options && options.etag !== void 0)
|
||||
this.#options.etag = options.etag;
|
||||
if (options.lastModified !== void 0) {
|
||||
if (!this.#options.lastModified || options.lastModified > this.#options.lastModified) {
|
||||
this.#options.lastModified = options.lastModified;
|
||||
}
|
||||
}
|
||||
if (options.tags) {
|
||||
for (const tag of options.tags) this.#tags.add(tag);
|
||||
}
|
||||
}
|
||||
get tags() {
|
||||
return [...this.#tags];
|
||||
}
|
||||
/**
|
||||
* Get the current cache options (read-only snapshot).
|
||||
* Includes all accumulated options: maxAge, swr, tags, etag, lastModified.
|
||||
*/
|
||||
get options() {
|
||||
return {
|
||||
...this.#options,
|
||||
tags: this.tags
|
||||
};
|
||||
}
|
||||
async invalidate(input) {
|
||||
if (!this.#provider) {
|
||||
throw new AstroError(CacheNotEnabled);
|
||||
}
|
||||
let options;
|
||||
if (isLiveDataEntry(input)) {
|
||||
options = { tags: input.cacheHint?.tags ?? [] };
|
||||
} else {
|
||||
options = input;
|
||||
}
|
||||
return this.#provider.invalidate(options);
|
||||
}
|
||||
/** @internal */
|
||||
[APPLY_HEADERS](response) {
|
||||
if (this.#disabled) return;
|
||||
const finalOptions = { ...this.#options, tags: this.tags };
|
||||
if (finalOptions.maxAge === void 0 && !finalOptions.tags?.length) return;
|
||||
const headers = this.#provider?.setHeaders?.(finalOptions) ?? defaultSetHeaders(finalOptions);
|
||||
for (const [key, value] of headers) {
|
||||
response.headers.set(key, value);
|
||||
}
|
||||
}
|
||||
/** @internal */
|
||||
get [IS_ACTIVE]() {
|
||||
return !this.#disabled && (this.#options.maxAge !== void 0 || this.#tags.size > 0);
|
||||
}
|
||||
}
|
||||
function applyCacheHeaders(cache, response) {
|
||||
if (APPLY_HEADERS in cache) {
|
||||
cache[APPLY_HEADERS](response);
|
||||
}
|
||||
}
|
||||
function isCacheActive(cache) {
|
||||
if (IS_ACTIVE in cache) {
|
||||
return cache[IS_ACTIVE];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
export {
|
||||
AstroCache,
|
||||
applyCacheHeaders,
|
||||
isCacheActive
|
||||
};
|
||||
26
node_modules/astro/dist/core/cache/runtime/noop.d.ts
generated
vendored
Normal file
26
node_modules/astro/dist/core/cache/runtime/noop.d.ts
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import type { CacheLike } from './cache.js';
|
||||
import type { CacheOptions } from '../types.js';
|
||||
import type { AstroLogger } from '../../logger/core.js';
|
||||
export declare class NoopAstroCache implements CacheLike {
|
||||
readonly enabled = false;
|
||||
set(): void;
|
||||
get tags(): string[];
|
||||
get options(): Readonly<CacheOptions>;
|
||||
invalidate(): Promise<void>;
|
||||
}
|
||||
/**
|
||||
* A no-op cache used when cache is not configured.
|
||||
* Logs a warning on first use instead of throwing, so libraries
|
||||
* can call cache methods without needing try/catch.
|
||||
* `invalidate()` still throws since it implies the caller
|
||||
* expects purging to actually work.
|
||||
*/
|
||||
export declare class DisabledAstroCache implements CacheLike {
|
||||
#private;
|
||||
readonly enabled = false;
|
||||
constructor(logger?: AstroLogger);
|
||||
set(): void;
|
||||
get tags(): string[];
|
||||
get options(): Readonly<CacheOptions>;
|
||||
invalidate(): Promise<void>;
|
||||
}
|
||||
49
node_modules/astro/dist/core/cache/runtime/noop.js
generated
vendored
Normal file
49
node_modules/astro/dist/core/cache/runtime/noop.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import { AstroError } from "../../errors/errors.js";
|
||||
import { CacheNotEnabled } from "../../errors/errors-data.js";
|
||||
const EMPTY_OPTIONS = Object.freeze({ tags: [] });
|
||||
class NoopAstroCache {
|
||||
enabled = false;
|
||||
set() {
|
||||
}
|
||||
get tags() {
|
||||
return [];
|
||||
}
|
||||
get options() {
|
||||
return EMPTY_OPTIONS;
|
||||
}
|
||||
async invalidate() {
|
||||
}
|
||||
}
|
||||
let hasWarned = false;
|
||||
class DisabledAstroCache {
|
||||
enabled = false;
|
||||
#logger;
|
||||
constructor(logger) {
|
||||
this.#logger = logger;
|
||||
}
|
||||
#warn() {
|
||||
if (!hasWarned) {
|
||||
hasWarned = true;
|
||||
this.#logger?.warn(
|
||||
"cache",
|
||||
"`cache.set()` was called but caching is not enabled. Configure a cache provider in your Astro config under `experimental.cache` to enable caching."
|
||||
);
|
||||
}
|
||||
}
|
||||
set() {
|
||||
this.#warn();
|
||||
}
|
||||
get tags() {
|
||||
return [];
|
||||
}
|
||||
get options() {
|
||||
return EMPTY_OPTIONS;
|
||||
}
|
||||
async invalidate() {
|
||||
throw new AstroError(CacheNotEnabled);
|
||||
}
|
||||
}
|
||||
export {
|
||||
DisabledAstroCache,
|
||||
NoopAstroCache
|
||||
};
|
||||
20
node_modules/astro/dist/core/cache/runtime/route-matching.d.ts
generated
vendored
Normal file
20
node_modules/astro/dist/core/cache/runtime/route-matching.d.ts
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { AstroConfig } from '../../../types/public/config.js';
|
||||
import type { RoutePart } from '../../../types/public/internal.js';
|
||||
import type { CacheOptions } from '../types.js';
|
||||
export interface CompiledCacheRoute {
|
||||
pattern: RegExp;
|
||||
options: CacheOptions;
|
||||
segments: RoutePart[][];
|
||||
route: string;
|
||||
}
|
||||
/**
|
||||
* Compile config-level cache route patterns into RegExps.
|
||||
* The result is memoized on the pipeline — this function is only called once,
|
||||
* on the first request that needs route matching.
|
||||
* Returns compiled patterns sorted by Astro's standard route priority (most specific first).
|
||||
*/
|
||||
export declare function compileCacheRoutes(routes: Record<string, CacheOptions>, base: AstroConfig['base'], trailingSlash: AstroConfig['trailingSlash']): CompiledCacheRoute[];
|
||||
/**
|
||||
* Called per-request to find the first matching cache rule for a given pathname.
|
||||
*/
|
||||
export declare function matchCacheRoute(pathname: string, compiledRoutes: CompiledCacheRoute[]): CacheOptions | null;
|
||||
28
node_modules/astro/dist/core/cache/runtime/route-matching.js
generated
vendored
Normal file
28
node_modules/astro/dist/core/cache/runtime/route-matching.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
import { removeLeadingForwardSlash } from "@astrojs/internal-helpers/path";
|
||||
import { getParts } from "../../routing/parts.js";
|
||||
import { getPattern } from "../../routing/pattern.js";
|
||||
import { routeComparator } from "../../routing/priority.js";
|
||||
function compileCacheRoutes(routes, base, trailingSlash) {
|
||||
const compiled = Object.entries(routes).map(([path, options]) => {
|
||||
const segments = removeLeadingForwardSlash(path).split("/").filter(Boolean).map((s) => getParts(s, path));
|
||||
const pattern = getPattern(segments, base, trailingSlash);
|
||||
return { pattern, options, segments, route: path };
|
||||
});
|
||||
compiled.sort(
|
||||
(a, b) => routeComparator(
|
||||
{ segments: a.segments, route: a.route, type: "page" },
|
||||
{ segments: b.segments, route: b.route, type: "page" }
|
||||
)
|
||||
);
|
||||
return compiled;
|
||||
}
|
||||
function matchCacheRoute(pathname, compiledRoutes) {
|
||||
for (const route of compiledRoutes) {
|
||||
if (route.pattern.test(pathname)) return route.options;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
export {
|
||||
compileCacheRoutes,
|
||||
matchCacheRoute
|
||||
};
|
||||
8
node_modules/astro/dist/core/cache/runtime/utils.d.ts
generated
vendored
Normal file
8
node_modules/astro/dist/core/cache/runtime/utils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import type { CacheHint, CacheOptions, LiveDataEntry } from '../types.js';
|
||||
/**
|
||||
* Generate default cache response headers from CacheOptions.
|
||||
* Used when the provider doesn't supply its own `setHeaders()`.
|
||||
*/
|
||||
export declare function defaultSetHeaders(options: CacheOptions): Headers;
|
||||
export declare function isCacheHint(value: unknown): value is CacheHint;
|
||||
export declare function isLiveDataEntry(value: unknown): value is LiveDataEntry;
|
||||
34
node_modules/astro/dist/core/cache/runtime/utils.js
generated
vendored
Normal file
34
node_modules/astro/dist/core/cache/runtime/utils.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
function defaultSetHeaders(options) {
|
||||
const headers = new Headers();
|
||||
const directives = [];
|
||||
if (options.maxAge !== void 0) {
|
||||
directives.push(`max-age=${options.maxAge}`);
|
||||
}
|
||||
if (options.swr !== void 0) {
|
||||
directives.push(`stale-while-revalidate=${options.swr}`);
|
||||
}
|
||||
if (directives.length > 0) {
|
||||
headers.set("CDN-Cache-Control", directives.join(", "));
|
||||
}
|
||||
if (options.tags && options.tags.length > 0) {
|
||||
headers.set("Cache-Tag", options.tags.join(", "));
|
||||
}
|
||||
if (options.lastModified) {
|
||||
headers.set("Last-Modified", options.lastModified.toUTCString());
|
||||
}
|
||||
if (options.etag) {
|
||||
headers.set("ETag", options.etag);
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
function isCacheHint(value) {
|
||||
return value != null && typeof value === "object" && "tags" in value;
|
||||
}
|
||||
function isLiveDataEntry(value) {
|
||||
return value != null && typeof value === "object" && "id" in value && "data" in value && "cacheHint" in value;
|
||||
}
|
||||
export {
|
||||
defaultSetHeaders,
|
||||
isCacheHint,
|
||||
isLiveDataEntry
|
||||
};
|
||||
66
node_modules/astro/dist/core/cache/types.d.ts
generated
vendored
Normal file
66
node_modules/astro/dist/core/cache/types.d.ts
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
import type { MiddlewareNext } from '../../types/public/common.js';
|
||||
import type { WaitUntilHook } from '../wait-until.js';
|
||||
export interface CacheOptions {
|
||||
maxAge?: number;
|
||||
swr?: number;
|
||||
tags?: string[];
|
||||
lastModified?: Date;
|
||||
etag?: string;
|
||||
}
|
||||
export interface CacheHint {
|
||||
tags?: string[];
|
||||
lastModified?: Date;
|
||||
}
|
||||
export interface LiveDataEntry {
|
||||
id: string;
|
||||
data: unknown;
|
||||
cacheHint?: CacheHint;
|
||||
}
|
||||
export interface InvalidateOptions {
|
||||
path?: string;
|
||||
tags?: string | string[];
|
||||
}
|
||||
export interface CacheProvider {
|
||||
name: string;
|
||||
setHeaders?(options: CacheOptions): Headers;
|
||||
onRequest?(context: {
|
||||
request: Request;
|
||||
url: URL;
|
||||
waitUntil?: WaitUntilHook;
|
||||
}, next: MiddlewareNext): Promise<Response>;
|
||||
invalidate(options: InvalidateOptions): Promise<void>;
|
||||
}
|
||||
export type CacheProviderFactory<TConfig extends Record<string, any> = Record<string, any>> = (config: TConfig | undefined) => CacheProvider;
|
||||
export interface CacheProviderConfig<TConfig extends Record<string, any> = Record<string, any>> {
|
||||
/** Optional display name for logs and errors */
|
||||
name?: string;
|
||||
/** URL or package import */
|
||||
entrypoint: string | URL;
|
||||
/** Serializable options used by the provider implementation */
|
||||
config?: TConfig;
|
||||
}
|
||||
export interface NormalizedCacheProviderConfig {
|
||||
name: string | undefined;
|
||||
entrypoint: string;
|
||||
config: Record<string, any> | undefined;
|
||||
}
|
||||
export interface SSRManifestCache {
|
||||
provider: string;
|
||||
options?: Record<string, any>;
|
||||
routes?: Record<string, CacheOptions>;
|
||||
}
|
||||
export interface RouteRule {
|
||||
/**
|
||||
* Cache max-age in seconds.
|
||||
*/
|
||||
maxAge?: number;
|
||||
/**
|
||||
* Stale-while-revalidate window in seconds.
|
||||
*/
|
||||
swr?: number;
|
||||
/**
|
||||
* Cache tags for invalidation.
|
||||
*/
|
||||
tags?: string[];
|
||||
}
|
||||
export type RouteRules = Record<string, RouteRule>;
|
||||
0
node_modules/astro/dist/core/cache/types.js
generated
vendored
Normal file
0
node_modules/astro/dist/core/cache/types.js
generated
vendored
Normal file
16
node_modules/astro/dist/core/cache/utils.d.ts
generated
vendored
Normal file
16
node_modules/astro/dist/core/cache/utils.d.ts
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import type { AstroConfig } from '../../types/public/index.js';
|
||||
import type { CacheOptions, CacheProviderConfig, NormalizedCacheProviderConfig, SSRManifestCache } from './types.js';
|
||||
export declare function normalizeCacheProviderConfig(provider: CacheProviderConfig): NormalizedCacheProviderConfig;
|
||||
/**
|
||||
* Normalize a route rule to extract cache options.
|
||||
*/
|
||||
export declare function normalizeRouteRuleCacheOptions(rule: {
|
||||
maxAge?: number;
|
||||
swr?: number;
|
||||
tags?: string[];
|
||||
} | undefined): CacheOptions | undefined;
|
||||
/**
|
||||
* Extract cache routes from experimental.routeRules config.
|
||||
*/
|
||||
export declare function extractCacheRoutesFromRouteRules(routeRules: AstroConfig['experimental']['routeRules']): Record<string, CacheOptions> | undefined;
|
||||
export declare function cacheConfigToManifest(cacheConfig: AstroConfig['experimental']['cache'], routeRulesConfig: AstroConfig['experimental']['routeRules']): SSRManifestCache | undefined;
|
||||
47
node_modules/astro/dist/core/cache/utils.js
generated
vendored
Normal file
47
node_modules/astro/dist/core/cache/utils.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
function normalizeCacheProviderConfig(provider) {
|
||||
return {
|
||||
name: provider.name,
|
||||
entrypoint: provider.entrypoint instanceof URL ? provider.entrypoint.href : provider.entrypoint,
|
||||
config: provider.config
|
||||
};
|
||||
}
|
||||
function normalizeRouteRuleCacheOptions(rule) {
|
||||
if (!rule) return void 0;
|
||||
if (rule.maxAge === void 0 && rule.swr === void 0 && rule.tags === void 0) {
|
||||
return void 0;
|
||||
}
|
||||
return {
|
||||
maxAge: rule.maxAge,
|
||||
swr: rule.swr,
|
||||
tags: rule.tags
|
||||
};
|
||||
}
|
||||
function extractCacheRoutesFromRouteRules(routeRules) {
|
||||
if (!routeRules) return void 0;
|
||||
const cacheRoutes = {};
|
||||
for (const [pattern, rule] of Object.entries(routeRules)) {
|
||||
const cacheOptions = normalizeRouteRuleCacheOptions(rule);
|
||||
if (cacheOptions) {
|
||||
cacheRoutes[pattern] = cacheOptions;
|
||||
}
|
||||
}
|
||||
return Object.keys(cacheRoutes).length > 0 ? cacheRoutes : void 0;
|
||||
}
|
||||
function cacheConfigToManifest(cacheConfig, routeRulesConfig) {
|
||||
if (!cacheConfig?.provider) {
|
||||
return void 0;
|
||||
}
|
||||
const provider = normalizeCacheProviderConfig(cacheConfig.provider);
|
||||
const routes = extractCacheRoutesFromRouteRules(routeRulesConfig);
|
||||
return {
|
||||
provider: provider.entrypoint,
|
||||
options: provider.config,
|
||||
routes
|
||||
};
|
||||
}
|
||||
export {
|
||||
cacheConfigToManifest,
|
||||
extractCacheRoutesFromRouteRules,
|
||||
normalizeCacheProviderConfig,
|
||||
normalizeRouteRuleCacheOptions
|
||||
};
|
||||
6
node_modules/astro/dist/core/cache/vite-plugin.d.ts
generated
vendored
Normal file
6
node_modules/astro/dist/core/cache/vite-plugin.d.ts
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { Plugin as VitePlugin } from 'vite';
|
||||
import type { AstroSettings } from '../../types/astro.js';
|
||||
export declare const VIRTUAL_CACHE_PROVIDER_ID = "virtual:astro:cache-provider";
|
||||
export declare function vitePluginCacheProvider({ settings, }: {
|
||||
settings: AstroSettings;
|
||||
}): VitePlugin | undefined;
|
||||
56
node_modules/astro/dist/core/cache/vite-plugin.js
generated
vendored
Normal file
56
node_modules/astro/dist/core/cache/vite-plugin.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { AstroError } from "../errors/errors.js";
|
||||
import { CacheProviderNotFound } from "../errors/errors-data.js";
|
||||
import { normalizeCacheProviderConfig } from "./utils.js";
|
||||
const VIRTUAL_CACHE_PROVIDER_ID = "virtual:astro:cache-provider";
|
||||
const RESOLVED_VIRTUAL_CACHE_PROVIDER_ID = "\0" + VIRTUAL_CACHE_PROVIDER_ID;
|
||||
function vitePluginCacheProvider({
|
||||
settings
|
||||
}) {
|
||||
const providerConfig = settings.config.experimental?.cache?.provider;
|
||||
if (!providerConfig) {
|
||||
return;
|
||||
}
|
||||
return {
|
||||
name: VIRTUAL_CACHE_PROVIDER_ID,
|
||||
enforce: "pre",
|
||||
resolveId: {
|
||||
filter: {
|
||||
id: new RegExp(`^${VIRTUAL_CACHE_PROVIDER_ID}$`)
|
||||
},
|
||||
handler() {
|
||||
return RESOLVED_VIRTUAL_CACHE_PROVIDER_ID;
|
||||
}
|
||||
},
|
||||
load: {
|
||||
filter: {
|
||||
id: new RegExp(`^${RESOLVED_VIRTUAL_CACHE_PROVIDER_ID}$`)
|
||||
},
|
||||
async handler() {
|
||||
const provider = normalizeCacheProviderConfig(providerConfig);
|
||||
const importerPath = fileURLToPath(new URL("package.json", settings.config.root));
|
||||
let resolved;
|
||||
try {
|
||||
resolved = await this.resolve(provider.entrypoint, importerPath);
|
||||
} catch {
|
||||
}
|
||||
if (!resolved) {
|
||||
const displayName = provider.name ?? provider.entrypoint;
|
||||
throw new AstroError({
|
||||
...CacheProviderNotFound,
|
||||
message: CacheProviderNotFound.message(displayName)
|
||||
});
|
||||
}
|
||||
return {
|
||||
code: `import { default as _default } from '${resolved.id}';
|
||||
export * from '${resolved.id}';
|
||||
export default _default;`
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
export {
|
||||
VIRTUAL_CACHE_PROVIDER_ID,
|
||||
vitePluginCacheProvider
|
||||
};
|
||||
Reference in New Issue
Block a user