astro 7.0.9 → 7.1.1
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/assets/fonts/infra/fs-font-file-content-resolver.js +1 -1
- package/dist/cli/dev/index.d.ts +17 -0
- package/dist/cli/dev/index.js +56 -2
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/content/consts.d.ts +2 -0
- package/dist/content/consts.js +4 -0
- package/dist/content/content-layer.d.ts +0 -6
- package/dist/content/content-layer.js +4 -9
- package/dist/content/data-store-source.d.ts +36 -0
- package/dist/content/data-store-source.js +30 -0
- package/dist/content/data-store-writer.d.ts +67 -0
- package/dist/content/data-store-writer.js +94 -0
- package/dist/content/data-store.d.ts +15 -0
- package/dist/content/data-store.js +33 -3
- package/dist/content/loaders/glob.d.ts +7 -0
- package/dist/content/loaders/glob.js +2 -2
- package/dist/content/mutable-data-store.d.ts +8 -0
- package/dist/content/mutable-data-store.js +52 -15
- package/dist/content/paths.d.ts +14 -0
- package/dist/content/paths.js +11 -0
- package/dist/content/runtime.js +4 -4
- package/dist/content/vite-plugin-content-virtual-mod.js +29 -2
- package/dist/core/app/dev/pipeline.js +2 -1
- package/dist/core/app/types.d.ts +39 -5
- package/dist/core/base-pipeline.d.ts +1 -1
- package/dist/core/base-pipeline.js +6 -2
- package/dist/core/build/index.js +2 -1
- package/dist/core/build/plugins/plugin-manifest.js +23 -8
- package/dist/core/config/schemas/base.d.ts +38 -5
- package/dist/core/config/schemas/base.js +15 -8
- package/dist/core/config/schemas/relative.d.ts +73 -15
- package/dist/core/constants.js +1 -1
- package/dist/core/csp/common.d.ts +7 -7
- package/dist/core/csp/common.js +8 -9
- package/dist/core/csp/config.d.ts +45 -0
- package/dist/core/csp/config.js +44 -2
- package/dist/core/csp/runtime.d.ts +21 -1
- package/dist/core/csp/runtime.js +31 -0
- package/dist/core/dev/dev.js +9 -4
- package/dist/core/dev/restart.js +7 -1
- package/dist/core/errors/zod-error-map.js +7 -1
- package/dist/core/fetch/fetch-state.js +77 -29
- package/dist/core/i18n/domain.d.ts +1 -1
- package/dist/core/i18n/domain.js +4 -5
- package/dist/core/logger/config.d.ts +1 -1
- package/dist/core/logger/core.d.ts +4 -4
- package/dist/core/logger/impls/console.d.ts +2 -2
- package/dist/core/logger/impls/json.d.ts +2 -2
- package/dist/core/logger/impls/json.js +3 -14
- package/dist/core/logger/impls/node.d.ts +2 -2
- package/dist/core/logger/load.d.ts +2 -2
- package/dist/core/logger/load.js +19 -27
- package/dist/core/messages/runtime.d.ts +8 -0
- package/dist/core/messages/runtime.js +34 -1
- package/dist/core/render/paginate.js +21 -16
- package/dist/core/sync/index.js +23 -8
- package/dist/integrations/hooks.js +8 -0
- package/dist/manifest/serialized.js +21 -6
- package/dist/runtime/server/escape.d.ts +2 -0
- package/dist/runtime/server/escape.js +4 -0
- package/dist/runtime/server/render/csp.js +80 -19
- package/dist/runtime/server/render/server-islands.js +6 -4
- package/dist/runtime/server/transition.js +2 -2
- package/dist/types/astro.d.ts +2 -3
- package/dist/types/public/common.d.ts +13 -0
- package/dist/types/public/config.d.ts +196 -15
- package/dist/types/public/context.d.ts +27 -11
- package/dist/types/public/internal.d.ts +12 -11
- package/dist/vite-plugin-app/pipeline.js +2 -1
- package/dist/vite-plugin-astro-server/route-guard.js +3 -2
- package/package.json +3 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import colors from "piccolore";
|
|
2
2
|
import {
|
|
3
3
|
collapseDuplicateLeadingSlashes,
|
|
4
|
+
collapseDuplicateSlashes,
|
|
4
5
|
prependForwardSlash,
|
|
5
6
|
removeTrailingForwardSlash
|
|
6
7
|
} from "@astrojs/internal-helpers/path";
|
|
@@ -16,7 +17,7 @@ import {
|
|
|
16
17
|
pipelineSymbol,
|
|
17
18
|
responseSentSymbol
|
|
18
19
|
} from "../constants.js";
|
|
19
|
-
import { pushDirective } from "../csp/runtime.js";
|
|
20
|
+
import { normalizeCspResourceEntry, pushDirective } from "../csp/runtime.js";
|
|
20
21
|
import { generateCspDigest } from "../encryption.js";
|
|
21
22
|
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
22
23
|
import {
|
|
@@ -28,7 +29,6 @@ import {
|
|
|
28
29
|
import { getParams, getProps } from "../render/index.js";
|
|
29
30
|
import { Rewrites } from "../rewrites/handler.js";
|
|
30
31
|
import { isRoute404or500, isRouteServerIsland } from "../routing/match.js";
|
|
31
|
-
import { normalizeUrl } from "../util/normalized-url.js";
|
|
32
32
|
import { MultiLevelEncodingError, validateAndDecodePathname } from "../util/pathname.js";
|
|
33
33
|
import { getOriginPathname, setOriginPathname } from "../routing/rewrite.js";
|
|
34
34
|
import { computePathnameFromDomain } from "../i18n/domain.js";
|
|
@@ -178,28 +178,29 @@ class FetchState {
|
|
|
178
178
|
this.componentInstance = void 0;
|
|
179
179
|
this.slots = void 0;
|
|
180
180
|
const url = new URL(request.url);
|
|
181
|
+
const publicPathname = this.#normalizePathname(url.pathname);
|
|
182
|
+
const pathname = this.#computePathname(publicPathname);
|
|
183
|
+
url.pathname = publicPathname;
|
|
184
|
+
url.pathname = collapseDuplicateSlashes(url.pathname);
|
|
181
185
|
const domainPathname = computePathnameFromDomain(
|
|
182
186
|
request,
|
|
183
187
|
url,
|
|
184
188
|
pipeline.manifest.i18n,
|
|
185
189
|
pipeline.manifest.base,
|
|
186
190
|
pipeline.manifest.trailingSlash,
|
|
187
|
-
pipeline.logger
|
|
191
|
+
pipeline.logger,
|
|
192
|
+
pathname
|
|
188
193
|
);
|
|
189
194
|
if (domainPathname) {
|
|
190
195
|
this.#domainPathname = domainPathname;
|
|
191
|
-
|
|
192
|
-
this.pathname = decodeURI(domainPathname);
|
|
193
|
-
} catch {
|
|
194
|
-
this.pathname = domainPathname;
|
|
195
|
-
}
|
|
196
|
+
this.pathname = domainPathname;
|
|
196
197
|
} else {
|
|
197
|
-
this.pathname =
|
|
198
|
+
this.pathname = pathname;
|
|
198
199
|
}
|
|
199
200
|
this.timeStart = performance.now();
|
|
200
201
|
this.clientAddress = options?.clientAddress;
|
|
201
202
|
this.locals = options?.locals ?? {};
|
|
202
|
-
this.url =
|
|
203
|
+
this.url = url;
|
|
203
204
|
this.cookies = new AstroCookies(request);
|
|
204
205
|
if (pipeline.manifest.allowedDomains && pipeline.manifest.allowedDomains.length > 0 && !this.routeData?.prerender) {
|
|
205
206
|
this.#applyForwardedHeaders();
|
|
@@ -304,12 +305,26 @@ class FetchState {
|
|
|
304
305
|
cspDestination: manifest.csp?.cspDestination ?? (routeData.prerender ? "meta" : "header"),
|
|
305
306
|
shouldInjectCspMetaTags,
|
|
306
307
|
cspAlgorithm,
|
|
308
|
+
directives: manifest.csp?.directives ? [...manifest.csp.directives] : [],
|
|
309
|
+
// Deprecated flat fields, kept for back-compat. Seeded from the manifest; the runtime CSP
|
|
310
|
+
// API updates the structured `scriptDirective`/`styleDirective` below (which the renderer
|
|
311
|
+
// reads), not these.
|
|
307
312
|
scriptHashes: manifest.csp?.scriptHashes ? [...manifest.csp.scriptHashes] : [],
|
|
308
313
|
scriptResources: manifest.csp?.scriptResources ? [...manifest.csp.scriptResources] : [],
|
|
309
314
|
styleHashes: manifest.csp?.styleHashes ? [...manifest.csp.styleHashes] : [],
|
|
310
315
|
styleResources: manifest.csp?.styleResources ? [...manifest.csp.styleResources] : [],
|
|
311
|
-
directives: manifest.csp?.directives ? [...manifest.csp.directives] : [],
|
|
312
316
|
isStrictDynamic: manifest.csp?.isStrictDynamic ?? false,
|
|
317
|
+
// Structured fields (source of truth). Arrays are cloned so per-request runtime inserts
|
|
318
|
+
// don't mutate the shared manifest.
|
|
319
|
+
scriptDirective: {
|
|
320
|
+
resources: manifest.csp?.scriptDirective ? [...manifest.csp.scriptDirective.resources] : [],
|
|
321
|
+
hashes: manifest.csp?.scriptDirective ? [...manifest.csp.scriptDirective.hashes] : [],
|
|
322
|
+
strictDynamic: manifest.csp?.scriptDirective?.strictDynamic ?? false
|
|
323
|
+
},
|
|
324
|
+
styleDirective: {
|
|
325
|
+
resources: manifest.csp?.styleDirective ? [...manifest.csp.styleDirective.resources] : [],
|
|
326
|
+
hashes: manifest.csp?.styleDirective ? [...manifest.csp.styleDirective.hashes] : []
|
|
327
|
+
},
|
|
313
328
|
internalFetchHeaders: manifest.internalFetchHeaders
|
|
314
329
|
};
|
|
315
330
|
this.result = result;
|
|
@@ -451,23 +466,51 @@ class FetchState {
|
|
|
451
466
|
}
|
|
452
467
|
return void 0;
|
|
453
468
|
}
|
|
469
|
+
const warnedFallback = /* @__PURE__ */ new Set();
|
|
470
|
+
const warnFallback = (family, kind) => {
|
|
471
|
+
if (kind === "default" || !state.result) {
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
const directive = family === "script" ? state.result.scriptDirective : state.result.styleDirective;
|
|
475
|
+
const defaultResources = directive.resources.map(normalizeCspResourceEntry).filter((entry) => entry.kind === "default").map((entry) => entry.resource);
|
|
476
|
+
if (defaultResources.length === 0) {
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
const key = `${family}:${kind}`;
|
|
480
|
+
if (warnedFallback.has(key)) {
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
warnedFallback.add(key);
|
|
484
|
+
const general = `${family}-src`;
|
|
485
|
+
const specific = `${general}-${kind === "element" ? "elem" : "attr"}`;
|
|
486
|
+
pipeline.logger.warn(
|
|
487
|
+
"csp",
|
|
488
|
+
`A resource was added to \`${specific}\`, but \`${general}\` also defines custom resources (${defaultResources.join(
|
|
489
|
+
" "
|
|
490
|
+
)}). Because \`${specific}\` overrides \`${general}\` for its scope (browsers do not fall back), those resources will not apply there. Add them to \`${specific}\` as well if needed.`
|
|
491
|
+
);
|
|
492
|
+
};
|
|
454
493
|
return {
|
|
455
494
|
insertDirective(payload) {
|
|
456
495
|
if (state.result) {
|
|
457
496
|
state.result.directives = pushDirective(state.result.directives, payload);
|
|
458
497
|
}
|
|
459
498
|
},
|
|
460
|
-
insertScriptResource(
|
|
461
|
-
state.result
|
|
499
|
+
insertScriptResource(payload) {
|
|
500
|
+
if (!state.result) return;
|
|
501
|
+
warnFallback("script", normalizeCspResourceEntry(payload).kind);
|
|
502
|
+
state.result.scriptDirective.resources.push(payload);
|
|
462
503
|
},
|
|
463
|
-
insertStyleResource(
|
|
464
|
-
state.result
|
|
504
|
+
insertStyleResource(payload) {
|
|
505
|
+
if (!state.result) return;
|
|
506
|
+
warnFallback("style", normalizeCspResourceEntry(payload).kind);
|
|
507
|
+
state.result.styleDirective.resources.push(payload);
|
|
465
508
|
},
|
|
466
|
-
insertStyleHash(
|
|
467
|
-
state.result?.
|
|
509
|
+
insertStyleHash(payload) {
|
|
510
|
+
state.result?.styleDirective.hashes.push(payload);
|
|
468
511
|
},
|
|
469
|
-
insertScriptHash(
|
|
470
|
-
state.result?.
|
|
512
|
+
insertScriptHash(payload) {
|
|
513
|
+
state.result?.scriptDirective.hashes.push(payload);
|
|
471
514
|
}
|
|
472
515
|
};
|
|
473
516
|
}
|
|
@@ -690,32 +733,37 @@ class FetchState {
|
|
|
690
733
|
this.#stripHtmlExtension();
|
|
691
734
|
}
|
|
692
735
|
/**
|
|
693
|
-
* Strips the pipeline's base from
|
|
694
|
-
*
|
|
695
|
-
* pathname if `decodeURI` throws.
|
|
736
|
+
* Strips the pipeline's base from a normalized request pathname and prepends
|
|
737
|
+
* a forward slash.
|
|
696
738
|
*
|
|
697
739
|
* Mirrors `BaseApp.removeBase`, including the
|
|
698
740
|
* `collapseDuplicateLeadingSlashes` fix that prevents middleware
|
|
699
741
|
* authorization bypass when the URL starts with `//`.
|
|
700
742
|
*/
|
|
701
|
-
#computePathname(
|
|
702
|
-
let pathname = collapseDuplicateLeadingSlashes(
|
|
743
|
+
#computePathname(normalizedPathname) {
|
|
744
|
+
let pathname = collapseDuplicateLeadingSlashes(normalizedPathname);
|
|
703
745
|
const base = this.pipeline.manifest.base;
|
|
704
746
|
if (pathname.startsWith(base)) {
|
|
705
747
|
const baseWithoutTrailingSlash = removeTrailingForwardSlash(base);
|
|
706
748
|
pathname = pathname.slice(baseWithoutTrailingSlash.length + 1);
|
|
707
749
|
}
|
|
708
|
-
|
|
750
|
+
return prependForwardSlash(pathname);
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Decodes and normalizes the public request pathname before deriving the
|
|
754
|
+
* separate pathname used for route matching.
|
|
755
|
+
*/
|
|
756
|
+
#normalizePathname(pathname) {
|
|
709
757
|
try {
|
|
710
|
-
|
|
758
|
+
pathname = validateAndDecodePathname(pathname);
|
|
711
759
|
} catch (e) {
|
|
712
760
|
if (e instanceof MultiLevelEncodingError) {
|
|
713
761
|
this.invalidEncoding = true;
|
|
714
|
-
|
|
762
|
+
} else {
|
|
763
|
+
this.pipeline.logger.error(null, e.toString());
|
|
715
764
|
}
|
|
716
|
-
this.pipeline.logger.error(null, e.toString());
|
|
717
|
-
return pathname;
|
|
718
765
|
}
|
|
766
|
+
return collapseDuplicateSlashes(pathname);
|
|
719
767
|
}
|
|
720
768
|
/**
|
|
721
769
|
* Reads X-Forwarded-Proto, X-Forwarded-Host, and X-Forwarded-Port
|
|
@@ -9,4 +9,4 @@ import type { AstroLogger } from '../logger/core.js';
|
|
|
9
9
|
* mapped to a locale — in which case normal pathname routing applies.
|
|
10
10
|
*
|
|
11
11
|
*/
|
|
12
|
-
export declare function computePathnameFromDomain(request: Request, url: URL, i18n: SSRManifest['i18n'], base: SSRManifest['base'], trailingSlash: SSRManifest['trailingSlash'], logger: AstroLogger): string | undefined;
|
|
12
|
+
export declare function computePathnameFromDomain(request: Request, url: URL, i18n: SSRManifest['i18n'], base: SSRManifest['base'], trailingSlash: SSRManifest['trailingSlash'], logger: AstroLogger, pathnameFromRequest?: string): string | undefined;
|
package/dist/core/i18n/domain.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
removeTrailingForwardSlash
|
|
7
7
|
} from "@astrojs/internal-helpers/path";
|
|
8
8
|
import { normalizeTheLocale } from "../../i18n/path.js";
|
|
9
|
-
function computePathnameFromDomain(request, url, i18n, base, trailingSlash, logger) {
|
|
9
|
+
function computePathnameFromDomain(request, url, i18n, base, trailingSlash, logger, pathnameFromRequest) {
|
|
10
10
|
let pathname = void 0;
|
|
11
11
|
if (i18n && (i18n.strategy === "domains-prefix-always" || i18n.strategy === "domains-prefix-other-locales" || i18n.strategy === "domains-prefix-always-no-redirect")) {
|
|
12
12
|
let host = request.headers.get("X-Forwarded-Host");
|
|
@@ -32,14 +32,13 @@ function computePathnameFromDomain(request, url, i18n, base, trailingSlash, logg
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
if (locale) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
);
|
|
35
|
+
const requestPathname = pathnameFromRequest ?? removeBase(url.pathname, base);
|
|
36
|
+
pathname = prependForwardSlash(joinPaths(normalizeTheLocale(locale), requestPathname));
|
|
38
37
|
if (trailingSlash === "always") {
|
|
39
38
|
pathname = appendForwardSlash(pathname);
|
|
40
39
|
} else if (trailingSlash === "never") {
|
|
41
40
|
pathname = removeTrailingForwardSlash(pathname);
|
|
42
|
-
} else if (
|
|
41
|
+
} else if (requestPathname.endsWith("/")) {
|
|
43
42
|
pathname = appendForwardSlash(pathname);
|
|
44
43
|
}
|
|
45
44
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export interface AstroLoggerDestination
|
|
1
|
+
export interface AstroLoggerDestination {
|
|
2
2
|
/**
|
|
3
3
|
* It receives a message and writes it into a destination
|
|
4
4
|
*/
|
|
5
|
-
write: (chunk:
|
|
5
|
+
write: (chunk: AstroLoggerMessage) => void;
|
|
6
6
|
/**
|
|
7
7
|
* It dumps logs without closing the connection to the destination.
|
|
8
8
|
* Method that can be used by specialized loggers.
|
|
@@ -31,7 +31,7 @@ export type AstroLoggerLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
|
31
31
|
declare const AstroLoggerLabels: readonly ["add", "build", "check", "config", "content", "crypto", "deprecated", "markdown", "router", "types", "vite", "watch", "middleware", "preferences", "redirects", "sync", "session", "toolbar", "assets", "env", "update", "adapter", "islands", "cache", "csp", "SKIP_FORMAT"];
|
|
32
32
|
type AstroLoggerLabel = (typeof AstroLoggerLabels)[number];
|
|
33
33
|
export interface AstroLogOptions {
|
|
34
|
-
destination: AstroLoggerDestination
|
|
34
|
+
destination: AstroLoggerDestination;
|
|
35
35
|
level: AstroLoggerLevel;
|
|
36
36
|
/**
|
|
37
37
|
* Optional configuration for the logger destination
|
|
@@ -78,7 +78,7 @@ export declare class AstroLogger {
|
|
|
78
78
|
debug(label: AstroLoggerLabel, ...messages: any[]): void;
|
|
79
79
|
level(): AstroLoggerLevel;
|
|
80
80
|
forkIntegrationLogger(label: string): AstroIntegrationLogger;
|
|
81
|
-
setDestination(destination: AstroLoggerDestination
|
|
81
|
+
setDestination(destination: AstroLoggerDestination): void;
|
|
82
82
|
/**
|
|
83
83
|
* It calls the `close` function of the provided destination, if it exists.
|
|
84
84
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type AstroLoggerDestination, type AstroLoggerLevel, AstroLogger } from '../core.js';
|
|
2
2
|
import type { NodeHandlerConfig } from './node.js';
|
|
3
3
|
export type ConsoleHandlerConfig = {
|
|
4
4
|
level?: AstroLoggerLevel;
|
|
@@ -6,4 +6,4 @@ export type ConsoleHandlerConfig = {
|
|
|
6
6
|
export declare function createConsoleLogger({ level }: {
|
|
7
7
|
level: AstroLoggerLevel;
|
|
8
8
|
}): AstroLogger;
|
|
9
|
-
export default function (options?: NodeHandlerConfig): AstroLoggerDestination
|
|
9
|
+
export default function (options?: NodeHandlerConfig): AstroLoggerDestination;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AstroLogger, type AstroLoggerDestination, type AstroLoggerLevel
|
|
1
|
+
import { AstroLogger, type AstroLoggerDestination, type AstroLoggerLevel } from '../core.js';
|
|
2
2
|
import type { AstroInlineConfig } from '../../../types/public/index.js';
|
|
3
3
|
export type JsonHandlerConfig = {
|
|
4
4
|
/**
|
|
@@ -11,5 +11,5 @@ export type JsonHandlerConfig = {
|
|
|
11
11
|
level?: AstroLoggerLevel;
|
|
12
12
|
};
|
|
13
13
|
export declare const SGR_REGEX: RegExp;
|
|
14
|
-
export default function jsonLoggerDestination(config?: JsonHandlerConfig): AstroLoggerDestination
|
|
14
|
+
export default function jsonLoggerDestination(config?: JsonHandlerConfig): AstroLoggerDestination;
|
|
15
15
|
export declare function createJsonLoggerFromFlags(config: AstroInlineConfig): AstroLogger;
|
|
@@ -8,24 +8,13 @@ function jsonLoggerDestination(config = {}) {
|
|
|
8
8
|
const { pretty = false, level = "info" } = config;
|
|
9
9
|
return {
|
|
10
10
|
write(event) {
|
|
11
|
-
let dest = process.stderr;
|
|
12
|
-
if (levels[event.level] < levels["error"]) {
|
|
13
|
-
dest = process.stdout;
|
|
14
|
-
}
|
|
15
11
|
if (!matchesLevel(event.level, level)) {
|
|
16
12
|
return;
|
|
17
13
|
}
|
|
18
|
-
|
|
14
|
+
const dest = levels[event.level] >= levels["error"] ? console.error : console.info;
|
|
19
15
|
const message = event.message.replace(SGR_REGEX, "");
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
JSON.stringify({ message, label: event.label, level: event.level }, null, 2) + trailingLine
|
|
23
|
-
);
|
|
24
|
-
} else {
|
|
25
|
-
dest.write(
|
|
26
|
-
JSON.stringify({ message, label: event.label, level: event.level }) + trailingLine
|
|
27
|
-
);
|
|
28
|
-
}
|
|
16
|
+
const payload = pretty ? JSON.stringify({ message, label: event.label, level: event.level }, null, 2) : JSON.stringify({ message, label: event.label, level: event.level });
|
|
17
|
+
dest(payload);
|
|
29
18
|
}
|
|
30
19
|
};
|
|
31
20
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { AstroLogger, type AstroLoggerDestination, type AstroLoggerLevel
|
|
1
|
+
import { AstroLogger, type AstroLoggerDestination, type AstroLoggerLevel } from '../core.js';
|
|
2
2
|
import type { AstroInlineConfig } from '../../../types/public/index.js';
|
|
3
3
|
export type NodeHandlerConfig = {
|
|
4
4
|
level?: AstroLoggerLevel;
|
|
5
5
|
};
|
|
6
|
-
export default function (options?: NodeHandlerConfig): AstroLoggerDestination
|
|
6
|
+
export default function (options?: NodeHandlerConfig): AstroLoggerDestination;
|
|
7
7
|
export declare function createNodeLoggerFromFlags(inlineConfig: AstroInlineConfig): AstroLogger;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { AstroLogger, type
|
|
1
|
+
import { AstroLogger, type AstroLoggerDestination } from './core.js';
|
|
2
2
|
import type { LoggerHandlerConfig } from './config.js';
|
|
3
3
|
import type { AstroConfig, AstroInlineConfig } from '../../types/public/index.js';
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function loadLoggerDestination(config: LoggerHandlerConfig): Promise<AstroLoggerDestination>;
|
|
5
5
|
/**
|
|
6
6
|
* It attempts to load a logger from the entrypoint.
|
|
7
7
|
* If not provided, it creates a new logger instance on the fly.
|
package/dist/core/logger/load.js
CHANGED
|
@@ -5,27 +5,22 @@ import { default as nodeLoggerCreator, createNodeLoggerFromFlags } from "./impls
|
|
|
5
5
|
import { default as consoleLoggerCreator } from "./impls/console.js";
|
|
6
6
|
import { default as jsonLoggerCreator } from "./impls/json.js";
|
|
7
7
|
import { default as composeLoggerCreator } from "./impls/compose.js";
|
|
8
|
-
|
|
8
|
+
function normalizeEntrypoint(entrypoint) {
|
|
9
|
+
return entrypoint instanceof URL ? entrypoint.href : entrypoint;
|
|
10
|
+
}
|
|
11
|
+
async function loadLoggerDestination(config) {
|
|
9
12
|
let cause = void 0;
|
|
13
|
+
const entrypoint = normalizeEntrypoint(config.entrypoint);
|
|
10
14
|
try {
|
|
11
15
|
switch (config.entrypoint) {
|
|
12
16
|
case "astro/logger/node": {
|
|
13
|
-
return
|
|
14
|
-
destination: nodeLoggerCreator(config.config),
|
|
15
|
-
level
|
|
16
|
-
});
|
|
17
|
+
return nodeLoggerCreator(config.config);
|
|
17
18
|
}
|
|
18
19
|
case "astro/logger/console": {
|
|
19
|
-
return
|
|
20
|
-
destination: consoleLoggerCreator(config.config),
|
|
21
|
-
level
|
|
22
|
-
});
|
|
20
|
+
return consoleLoggerCreator(config.config);
|
|
23
21
|
}
|
|
24
22
|
case "astro/logger/json": {
|
|
25
|
-
return
|
|
26
|
-
destination: jsonLoggerCreator(config.config),
|
|
27
|
-
level
|
|
28
|
-
});
|
|
23
|
+
return jsonLoggerCreator(config.config);
|
|
29
24
|
}
|
|
30
25
|
case "astro/logger/compose": {
|
|
31
26
|
let destinations = [];
|
|
@@ -35,26 +30,20 @@ async function loadLogger(config, level = "info") {
|
|
|
35
30
|
loggers.map(async (loggerConfig) => {
|
|
36
31
|
const logger = await import(
|
|
37
32
|
/* @vite-ignore */
|
|
38
|
-
loggerConfig.entrypoint
|
|
33
|
+
normalizeEntrypoint(loggerConfig.entrypoint)
|
|
39
34
|
);
|
|
40
35
|
return logger.default(loggerConfig.config);
|
|
41
36
|
})
|
|
42
37
|
);
|
|
43
38
|
}
|
|
44
|
-
return
|
|
45
|
-
destination: composeLoggerCreator(destinations),
|
|
46
|
-
level
|
|
47
|
-
});
|
|
39
|
+
return composeLoggerCreator(destinations);
|
|
48
40
|
}
|
|
49
41
|
default: {
|
|
50
|
-
const
|
|
42
|
+
const logger = await import(
|
|
51
43
|
/* @vite-ignore */
|
|
52
|
-
|
|
44
|
+
entrypoint
|
|
53
45
|
);
|
|
54
|
-
return
|
|
55
|
-
destination: nodeLogger.default(config.config),
|
|
56
|
-
level
|
|
57
|
-
});
|
|
46
|
+
return logger.default(config.config);
|
|
58
47
|
}
|
|
59
48
|
}
|
|
60
49
|
} catch (e) {
|
|
@@ -64,7 +53,7 @@ async function loadLogger(config, level = "info") {
|
|
|
64
53
|
}
|
|
65
54
|
const error = new AstroError({
|
|
66
55
|
...UnableToLoadLogger,
|
|
67
|
-
message: UnableToLoadLogger.message(
|
|
56
|
+
message: UnableToLoadLogger.message(entrypoint)
|
|
68
57
|
});
|
|
69
58
|
if (cause) {
|
|
70
59
|
error.cause = cause;
|
|
@@ -75,7 +64,10 @@ async function loadOrCreateNodeLogger(astroConfig, inlineAstroConfig) {
|
|
|
75
64
|
if (inlineAstroConfig._logger) return inlineAstroConfig._logger;
|
|
76
65
|
try {
|
|
77
66
|
if (astroConfig.logger) {
|
|
78
|
-
return
|
|
67
|
+
return new AstroLogger({
|
|
68
|
+
destination: await loadLoggerDestination(astroConfig.logger),
|
|
69
|
+
level: inlineAstroConfig.logLevel ?? "info"
|
|
70
|
+
});
|
|
79
71
|
} else {
|
|
80
72
|
return createNodeLoggerFromFlags(inlineAstroConfig);
|
|
81
73
|
}
|
|
@@ -84,6 +76,6 @@ async function loadOrCreateNodeLogger(astroConfig, inlineAstroConfig) {
|
|
|
84
76
|
}
|
|
85
77
|
}
|
|
86
78
|
export {
|
|
87
|
-
|
|
79
|
+
loadLoggerDestination,
|
|
88
80
|
loadOrCreateNodeLogger
|
|
89
81
|
};
|
|
@@ -58,3 +58,11 @@ export declare function printHelp({ commandName, headline, usage, tables, descri
|
|
|
58
58
|
description?: string;
|
|
59
59
|
}): void;
|
|
60
60
|
export declare function warnIfCspWithShiki(config: AstroConfig, logger: AstroLogger): void;
|
|
61
|
+
/**
|
|
62
|
+
* Warns when a `scriptDirective`/`styleDirective` defines `default`-kind resources alongside
|
|
63
|
+
* `element`/`attribute`-kind entries. Because the more specific directive (`*-src-elem`/`*-src-attr`)
|
|
64
|
+
* overrides the generic one for its scope and browsers do not fall back, the generic resources will
|
|
65
|
+
* not apply there. Astro's generated hashes are folded automatically, so this only concerns
|
|
66
|
+
* user-provided resources.
|
|
67
|
+
*/
|
|
68
|
+
export declare function warnIfCspResourceFallbackShadowing(config: AstroConfig, logger: AstroLogger): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import colors from "piccolore";
|
|
2
|
+
import { partitionByKind } from "../csp/runtime.js";
|
|
2
3
|
import { getDocsForError, renderErrorMarkdown } from "../errors/dev/runtime.js";
|
|
3
4
|
import {
|
|
4
5
|
AstroError,
|
|
@@ -269,7 +270,7 @@ function printHelp({
|
|
|
269
270
|
message.push(
|
|
270
271
|
linebreak(),
|
|
271
272
|
` ${bgGreen(black(` ${commandName} `))} ${green(
|
|
272
|
-
`v${"7.
|
|
273
|
+
`v${"7.1.1"}`
|
|
273
274
|
)} ${headline}`
|
|
274
275
|
);
|
|
275
276
|
}
|
|
@@ -304,6 +305,37 @@ function warnIfCspWithShiki(config, logger) {
|
|
|
304
305
|
);
|
|
305
306
|
}
|
|
306
307
|
}
|
|
308
|
+
function warnIfCspResourceFallbackShadowing(config, logger) {
|
|
309
|
+
const csp = config.security.csp;
|
|
310
|
+
if (typeof csp !== "object") return;
|
|
311
|
+
const families = [
|
|
312
|
+
{ name: "script", directive: csp.scriptDirective },
|
|
313
|
+
{ name: "style", directive: csp.styleDirective }
|
|
314
|
+
];
|
|
315
|
+
for (const { name, directive } of families) {
|
|
316
|
+
const sources = partitionByKind({
|
|
317
|
+
resources: directive?.resources ?? [],
|
|
318
|
+
hashes: directive?.hashes ?? []
|
|
319
|
+
});
|
|
320
|
+
if (sources.default.resources.length === 0) continue;
|
|
321
|
+
const shadowed = [];
|
|
322
|
+
if (sources.element.resources.length > 0 || sources.element.hashes.length > 0) {
|
|
323
|
+
shadowed.push(`\`${name}-src-elem\``);
|
|
324
|
+
}
|
|
325
|
+
if (sources.attribute.resources.length > 0 || sources.attribute.hashes.length > 0) {
|
|
326
|
+
shadowed.push(`\`${name}-src-attr\``);
|
|
327
|
+
}
|
|
328
|
+
if (shadowed.length === 0) continue;
|
|
329
|
+
logger.warn(
|
|
330
|
+
"csp",
|
|
331
|
+
`\`security.csp.${name}Directive\` defines \`${name}-src\` resources (${sources.default.resources.join(
|
|
332
|
+
" "
|
|
333
|
+
)}) as well as ${shadowed.join(" and ")} resources or hashes. Because ${shadowed.join(
|
|
334
|
+
" and "
|
|
335
|
+
)} override \`${name}-src\` for their scope (browsers do not fall back), those \`${name}-src\` resources will not apply there. Add them to the corresponding \`kind\` if needed.`
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
307
339
|
export {
|
|
308
340
|
actionRequired,
|
|
309
341
|
cancelled,
|
|
@@ -327,5 +359,6 @@ export {
|
|
|
327
359
|
telemetryEnabled,
|
|
328
360
|
telemetryNotice,
|
|
329
361
|
telemetryReset,
|
|
362
|
+
warnIfCspResourceFallbackShadowing,
|
|
330
363
|
warnIfCspWithShiki
|
|
331
364
|
};
|
|
@@ -4,11 +4,12 @@ import { getRouteGenerator } from "../routing/generator.js";
|
|
|
4
4
|
function generatePaginateFunction(routeMatch, base, trailingSlash) {
|
|
5
5
|
return function paginateUtility(data, args = {}) {
|
|
6
6
|
const generate = getRouteGenerator(routeMatch.segments, trailingSlash);
|
|
7
|
-
let { pageSize: _pageSize, params: _params, props: _props } = args;
|
|
7
|
+
let { pageSize: _pageSize, params: _params, props: _props, format: _format } = args;
|
|
8
8
|
const pageSize = _pageSize || 10;
|
|
9
9
|
const paramName = "page";
|
|
10
10
|
const additionalParams = _params || {};
|
|
11
11
|
const additionalProps = _props || {};
|
|
12
|
+
const formatUrl = _format || ((url) => url);
|
|
12
13
|
let includesFirstPageNumber;
|
|
13
14
|
if (routeMatch.params.includes(`...${paramName}`)) {
|
|
14
15
|
includesFirstPageNumber = false;
|
|
@@ -29,23 +30,27 @@ function generatePaginateFunction(routeMatch, base, trailingSlash) {
|
|
|
29
30
|
...additionalParams,
|
|
30
31
|
[paramName]: includesFirstPageNumber || pageNum > 1 ? String(pageNum) : void 0
|
|
31
32
|
};
|
|
32
|
-
const current = addRouteBase(generate({ ...params }), base);
|
|
33
|
-
const next = pageNum === lastPage ? void 0 : addRouteBase(generate({ ...params, page: String(pageNum + 1) }), base);
|
|
34
|
-
const prev = pageNum === 1 ? void 0 :
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
const current = formatUrl(addRouteBase(generate({ ...params }), base));
|
|
34
|
+
const next = pageNum === lastPage ? void 0 : formatUrl(addRouteBase(generate({ ...params, page: String(pageNum + 1) }), base));
|
|
35
|
+
const prev = pageNum === 1 ? void 0 : formatUrl(
|
|
36
|
+
addRouteBase(
|
|
37
|
+
generate({
|
|
38
|
+
...params,
|
|
39
|
+
page: !includesFirstPageNumber && pageNum - 1 === 1 ? void 0 : String(pageNum - 1)
|
|
40
|
+
}),
|
|
41
|
+
base
|
|
42
|
+
)
|
|
40
43
|
);
|
|
41
|
-
const first = pageNum === 1 ? void 0 :
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
const first = pageNum === 1 ? void 0 : formatUrl(
|
|
45
|
+
addRouteBase(
|
|
46
|
+
generate({
|
|
47
|
+
...params,
|
|
48
|
+
page: includesFirstPageNumber ? "1" : void 0
|
|
49
|
+
}),
|
|
50
|
+
base
|
|
51
|
+
)
|
|
47
52
|
);
|
|
48
|
-
const last = pageNum === lastPage ? void 0 : addRouteBase(generate({ ...params, page: String(lastPage) }), base);
|
|
53
|
+
const last = pageNum === lastPage ? void 0 : formatUrl(addRouteBase(generate({ ...params, page: String(lastPage) }), base));
|
|
49
54
|
return {
|
|
50
55
|
params,
|
|
51
56
|
props: {
|
package/dist/core/sync/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import colors from "piccolore";
|
|
|
6
6
|
import { createServer } from "vite";
|
|
7
7
|
import { syncFonts } from "../../assets/fonts/sync.js";
|
|
8
8
|
import { CONTENT_TYPES_FILE } from "../../content/consts.js";
|
|
9
|
-
import { getDataStoreFile } from "../../content/
|
|
9
|
+
import { getDataStoreDir, getDataStoreFile } from "../../content/paths.js";
|
|
10
10
|
import { globalContentLayer } from "../../content/instance.js";
|
|
11
11
|
import { createContentTypesGenerator } from "../../content/index.js";
|
|
12
12
|
import { MutableDataStore } from "../../content/mutable-data-store.js";
|
|
@@ -59,11 +59,21 @@ async function clearContentLayerCache({
|
|
|
59
59
|
fs = fsMod,
|
|
60
60
|
isDev
|
|
61
61
|
}) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
if (settings.config.experimental.collectionStorage === "chunked") {
|
|
63
|
+
const dataStore = getDataStoreDir(settings, isDev);
|
|
64
|
+
if (fs.existsSync(dataStore)) {
|
|
65
|
+
logger.debug("content", "clearing data store");
|
|
66
|
+
await fs.promises.rm(dataStore, { force: true, recursive: true });
|
|
67
|
+
await fs.promises.mkdir(dataStore, { recursive: true });
|
|
68
|
+
logger.warn("content", "data store cleared (force)");
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
const dataStore = getDataStoreFile(settings, isDev);
|
|
72
|
+
if (fs.existsSync(dataStore)) {
|
|
73
|
+
logger.debug("content", "clearing data store");
|
|
74
|
+
await fs.promises.rm(dataStore, { force: true });
|
|
75
|
+
logger.warn("content", "data store cleared (force)");
|
|
76
|
+
}
|
|
67
77
|
}
|
|
68
78
|
}
|
|
69
79
|
async function syncInternal({
|
|
@@ -88,8 +98,13 @@ async function syncInternal({
|
|
|
88
98
|
settings.timer.start("Sync content layer");
|
|
89
99
|
let store;
|
|
90
100
|
try {
|
|
91
|
-
|
|
92
|
-
|
|
101
|
+
if (settings.config.experimental.collectionStorage === "chunked") {
|
|
102
|
+
const dataStoreDir = getDataStoreDir(settings, isDev);
|
|
103
|
+
store = await MutableDataStore.fromDir(dataStoreDir);
|
|
104
|
+
} else {
|
|
105
|
+
const dataStoreFile = getDataStoreFile(settings, isDev);
|
|
106
|
+
store = await MutableDataStore.fromFile(dataStoreFile);
|
|
107
|
+
}
|
|
93
108
|
} catch (err) {
|
|
94
109
|
logger.error("content", err.message);
|
|
95
110
|
}
|