astro 7.0.8 → 7.1.0
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 +37 -8
- 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 +52 -10
- 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/astro-island.js +1 -3
- package/dist/runtime/server/astro-island.prebuilt-dev.d.ts +1 -1
- package/dist/runtime/server/astro-island.prebuilt-dev.js +1 -1
- package/dist/runtime/server/astro-island.prebuilt.d.ts +1 -1
- package/dist/runtime/server/astro-island.prebuilt.js +1 -1
- 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
|
@@ -256,12 +256,40 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
256
256
|
}>>>;
|
|
257
257
|
directives: z.ZodOptional<z.ZodArray<z.ZodCustom<`base-uri${string}` | `child-src${string}` | `connect-src${string}` | `default-src${string}` | `fenced-frame-src${string}` | `font-src${string}` | `form-action${string}` | `frame-ancestors${string}` | `frame-src${string}` | `img-src${string}` | `manifest-src${string}` | `media-src${string}` | `object-src${string}` | `referrer${string}` | `report-to${string}` | `report-uri${string}` | `require-trusted-types-for${string}` | `sandbox${string}` | `trusted-types${string}` | `upgrade-insecure-requests${string}` | `worker-src${string}`, `base-uri${string}` | `child-src${string}` | `connect-src${string}` | `default-src${string}` | `fenced-frame-src${string}` | `font-src${string}` | `form-action${string}` | `frame-ancestors${string}` | `frame-src${string}` | `img-src${string}` | `manifest-src${string}` | `media-src${string}` | `object-src${string}` | `referrer${string}` | `report-to${string}` | `report-uri${string}` | `require-trusted-types-for${string}` | `sandbox${string}` | `trusted-types${string}` | `upgrade-insecure-requests${string}` | `worker-src${string}`>>>;
|
|
258
258
|
styleDirective: z.ZodOptional<z.ZodObject<{
|
|
259
|
-
resources: z.ZodOptional<z.ZodArray<z.ZodString
|
|
260
|
-
|
|
259
|
+
resources: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
260
|
+
resource: z.ZodString;
|
|
261
|
+
kind: z.ZodEnum<{
|
|
262
|
+
default: "default";
|
|
263
|
+
attribute: "attribute";
|
|
264
|
+
element: "element";
|
|
265
|
+
}>;
|
|
266
|
+
}, z.core.$strip>]>>>;
|
|
267
|
+
hashes: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodCustom<`sha256-${string}` | `sha384-${string}` | `sha512-${string}`, `sha256-${string}` | `sha384-${string}` | `sha512-${string}`>, z.ZodObject<{
|
|
268
|
+
hash: z.ZodCustom<`sha256-${string}` | `sha384-${string}` | `sha512-${string}`, `sha256-${string}` | `sha384-${string}` | `sha512-${string}`>;
|
|
269
|
+
kind: z.ZodEnum<{
|
|
270
|
+
default: "default";
|
|
271
|
+
attribute: "attribute";
|
|
272
|
+
element: "element";
|
|
273
|
+
}>;
|
|
274
|
+
}, z.core.$strip>]>>>;
|
|
261
275
|
}, z.core.$strip>>;
|
|
262
276
|
scriptDirective: z.ZodOptional<z.ZodObject<{
|
|
263
|
-
resources: z.ZodOptional<z.ZodArray<z.ZodString
|
|
264
|
-
|
|
277
|
+
resources: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
278
|
+
resource: z.ZodString;
|
|
279
|
+
kind: z.ZodEnum<{
|
|
280
|
+
default: "default";
|
|
281
|
+
attribute: "attribute";
|
|
282
|
+
element: "element";
|
|
283
|
+
}>;
|
|
284
|
+
}, z.core.$strip>]>>>;
|
|
285
|
+
hashes: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodCustom<`sha256-${string}` | `sha384-${string}` | `sha512-${string}`, `sha256-${string}` | `sha384-${string}` | `sha512-${string}`>, z.ZodObject<{
|
|
286
|
+
hash: z.ZodCustom<`sha256-${string}` | `sha384-${string}` | `sha512-${string}`, `sha256-${string}` | `sha384-${string}` | `sha512-${string}`>;
|
|
287
|
+
kind: z.ZodEnum<{
|
|
288
|
+
default: "default";
|
|
289
|
+
attribute: "attribute";
|
|
290
|
+
element: "element";
|
|
291
|
+
}>;
|
|
292
|
+
}, z.core.$strip>]>>>;
|
|
265
293
|
strictDynamic: z.ZodOptional<z.ZodBoolean>;
|
|
266
294
|
}, z.core.$strip>>;
|
|
267
295
|
}, z.core.$strip>]>>>;
|
|
@@ -346,7 +374,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
346
374
|
}>>>;
|
|
347
375
|
fetchFile: z.ZodDefault<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
348
376
|
logger: z.ZodOptional<z.ZodObject<{
|
|
349
|
-
entrypoint: z.ZodString
|
|
377
|
+
entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
|
|
350
378
|
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
351
379
|
}, z.core.$strip>>;
|
|
352
380
|
fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -412,6 +440,10 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
412
440
|
name: z.ZodString;
|
|
413
441
|
optimize: z.ZodCustom<(contents: string) => string | Promise<string>, (contents: string) => string | Promise<string>>;
|
|
414
442
|
}, z.core.$strip>>;
|
|
443
|
+
collectionStorage: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
444
|
+
"single-file": "single-file";
|
|
445
|
+
chunked: "chunked";
|
|
446
|
+
}>>>;
|
|
415
447
|
}, z.core.$strict>>;
|
|
416
448
|
legacy: z.ZodPrefault<z.ZodObject<{
|
|
417
449
|
collectionsBackwardsCompat: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -528,12 +560,24 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
528
560
|
algorithm: "SHA-256" | "SHA-384" | "SHA-512";
|
|
529
561
|
directives?: (`base-uri${string}` | `child-src${string}` | `connect-src${string}` | `default-src${string}` | `fenced-frame-src${string}` | `font-src${string}` | `form-action${string}` | `frame-ancestors${string}` | `frame-src${string}` | `img-src${string}` | `manifest-src${string}` | `media-src${string}` | `object-src${string}` | `referrer${string}` | `report-to${string}` | `report-uri${string}` | `require-trusted-types-for${string}` | `sandbox${string}` | `trusted-types${string}` | `upgrade-insecure-requests${string}` | `worker-src${string}`)[] | undefined;
|
|
530
562
|
styleDirective?: {
|
|
531
|
-
resources?: string
|
|
532
|
-
|
|
563
|
+
resources?: (string | {
|
|
564
|
+
resource: string;
|
|
565
|
+
kind: "default" | "attribute" | "element";
|
|
566
|
+
})[] | undefined;
|
|
567
|
+
hashes?: (`sha256-${string}` | `sha384-${string}` | `sha512-${string}` | {
|
|
568
|
+
hash: `sha256-${string}` | `sha384-${string}` | `sha512-${string}`;
|
|
569
|
+
kind: "default" | "attribute" | "element";
|
|
570
|
+
})[] | undefined;
|
|
533
571
|
} | undefined;
|
|
534
572
|
scriptDirective?: {
|
|
535
|
-
resources?: string
|
|
536
|
-
|
|
573
|
+
resources?: (string | {
|
|
574
|
+
resource: string;
|
|
575
|
+
kind: "default" | "attribute" | "element";
|
|
576
|
+
})[] | undefined;
|
|
577
|
+
hashes?: (`sha256-${string}` | `sha384-${string}` | `sha512-${string}` | {
|
|
578
|
+
hash: `sha256-${string}` | `sha384-${string}` | `sha512-${string}`;
|
|
579
|
+
kind: "default" | "attribute" | "element";
|
|
580
|
+
})[] | undefined;
|
|
537
581
|
strictDynamic?: boolean | undefined;
|
|
538
582
|
} | undefined;
|
|
539
583
|
};
|
|
@@ -586,6 +630,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
586
630
|
clientPrerender: boolean;
|
|
587
631
|
contentIntellisense: boolean;
|
|
588
632
|
chromeDevtoolsWorkspace: boolean;
|
|
633
|
+
collectionStorage: "single-file" | "chunked";
|
|
589
634
|
svgOptimizer?: {
|
|
590
635
|
name: string;
|
|
591
636
|
optimize: (contents: string) => string | Promise<string>;
|
|
@@ -664,7 +709,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
664
709
|
ttl?: number | undefined;
|
|
665
710
|
} | undefined;
|
|
666
711
|
logger?: {
|
|
667
|
-
entrypoint: string;
|
|
712
|
+
entrypoint: string | URL;
|
|
668
713
|
config?: Record<string, any> | undefined;
|
|
669
714
|
} | undefined;
|
|
670
715
|
fonts?: {
|
|
@@ -778,12 +823,24 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
778
823
|
algorithm: "SHA-256" | "SHA-384" | "SHA-512";
|
|
779
824
|
directives?: (`base-uri${string}` | `child-src${string}` | `connect-src${string}` | `default-src${string}` | `fenced-frame-src${string}` | `font-src${string}` | `form-action${string}` | `frame-ancestors${string}` | `frame-src${string}` | `img-src${string}` | `manifest-src${string}` | `media-src${string}` | `object-src${string}` | `referrer${string}` | `report-to${string}` | `report-uri${string}` | `require-trusted-types-for${string}` | `sandbox${string}` | `trusted-types${string}` | `upgrade-insecure-requests${string}` | `worker-src${string}`)[] | undefined;
|
|
780
825
|
styleDirective?: {
|
|
781
|
-
resources?: string
|
|
782
|
-
|
|
826
|
+
resources?: (string | {
|
|
827
|
+
resource: string;
|
|
828
|
+
kind: "default" | "attribute" | "element";
|
|
829
|
+
})[] | undefined;
|
|
830
|
+
hashes?: (`sha256-${string}` | `sha384-${string}` | `sha512-${string}` | {
|
|
831
|
+
hash: `sha256-${string}` | `sha384-${string}` | `sha512-${string}`;
|
|
832
|
+
kind: "default" | "attribute" | "element";
|
|
833
|
+
})[] | undefined;
|
|
783
834
|
} | undefined;
|
|
784
835
|
scriptDirective?: {
|
|
785
|
-
resources?: string
|
|
786
|
-
|
|
836
|
+
resources?: (string | {
|
|
837
|
+
resource: string;
|
|
838
|
+
kind: "default" | "attribute" | "element";
|
|
839
|
+
})[] | undefined;
|
|
840
|
+
hashes?: (`sha256-${string}` | `sha384-${string}` | `sha512-${string}` | {
|
|
841
|
+
hash: `sha256-${string}` | `sha384-${string}` | `sha512-${string}`;
|
|
842
|
+
kind: "default" | "attribute" | "element";
|
|
843
|
+
})[] | undefined;
|
|
787
844
|
strictDynamic?: boolean | undefined;
|
|
788
845
|
} | undefined;
|
|
789
846
|
};
|
|
@@ -836,6 +893,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
836
893
|
clientPrerender: boolean;
|
|
837
894
|
contentIntellisense: boolean;
|
|
838
895
|
chromeDevtoolsWorkspace: boolean;
|
|
896
|
+
collectionStorage: "single-file" | "chunked";
|
|
839
897
|
svgOptimizer?: {
|
|
840
898
|
name: string;
|
|
841
899
|
optimize: (contents: string) => string | Promise<string>;
|
|
@@ -914,7 +972,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
914
972
|
ttl?: number | undefined;
|
|
915
973
|
} | undefined;
|
|
916
974
|
logger?: {
|
|
917
|
-
entrypoint: string;
|
|
975
|
+
entrypoint: string | URL;
|
|
918
976
|
config?: Record<string, any> | undefined;
|
|
919
977
|
} | undefined;
|
|
920
978
|
fonts?: {
|
package/dist/core/constants.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import type { AstroSettings } from '../../types/astro.js';
|
|
2
2
|
import type { AstroConfig, CspAlgorithm } from '../../types/public/index.js';
|
|
3
3
|
import type { BuildInternals } from '../build/internal.js';
|
|
4
|
-
import type { CspDirective } from './config.js';
|
|
4
|
+
import type { CspDirective, CspHash, CspHashEntry, CspResourceEntry } from './config.js';
|
|
5
5
|
type EnabledCsp = Exclude<AstroConfig['security']['csp'], false>;
|
|
6
6
|
export declare function shouldTrackCspHashes(csp: any): csp is EnabledCsp;
|
|
7
7
|
export declare function getAlgorithm(csp: EnabledCsp): CspAlgorithm;
|
|
8
|
-
export declare function
|
|
9
|
-
export declare function
|
|
10
|
-
export declare function
|
|
11
|
-
export declare function
|
|
8
|
+
export declare function getScriptResources(csp: EnabledCsp): CspResourceEntry[];
|
|
9
|
+
export declare function getScriptHashes(csp: EnabledCsp): CspHashEntry[];
|
|
10
|
+
export declare function getStyleResources(csp: EnabledCsp): CspResourceEntry[];
|
|
11
|
+
export declare function getStyleHashes(csp: EnabledCsp): CspHashEntry[];
|
|
12
12
|
export declare function getDirectives(settings: AstroSettings): CspDirective[];
|
|
13
13
|
export declare function getStrictDynamic(csp: EnabledCsp): boolean;
|
|
14
|
-
export declare function trackStyleHashes(internals: BuildInternals, settings: AstroSettings, algorithm: CspAlgorithm): Promise<
|
|
15
|
-
export declare function trackScriptHashes(internals: BuildInternals, settings: AstroSettings, algorithm: CspAlgorithm): Promise<
|
|
14
|
+
export declare function trackStyleHashes(internals: BuildInternals, settings: AstroSettings, algorithm: CspAlgorithm): Promise<CspHash[]>;
|
|
15
|
+
export declare function trackScriptHashes(internals: BuildInternals, settings: AstroSettings, algorithm: CspAlgorithm): Promise<CspHash[]>;
|
|
16
16
|
export {};
|
package/dist/core/csp/common.js
CHANGED
|
@@ -13,24 +13,17 @@ function getAlgorithm(csp) {
|
|
|
13
13
|
}
|
|
14
14
|
return csp.algorithm;
|
|
15
15
|
}
|
|
16
|
-
function getScriptHashes(csp) {
|
|
17
|
-
if (csp === true) {
|
|
18
|
-
return [];
|
|
19
|
-
} else {
|
|
20
|
-
return csp.scriptDirective?.hashes ?? [];
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
16
|
function getScriptResources(csp) {
|
|
24
17
|
if (csp === true) {
|
|
25
18
|
return [];
|
|
26
19
|
}
|
|
27
20
|
return csp.scriptDirective?.resources ?? [];
|
|
28
21
|
}
|
|
29
|
-
function
|
|
22
|
+
function getScriptHashes(csp) {
|
|
30
23
|
if (csp === true) {
|
|
31
24
|
return [];
|
|
32
25
|
}
|
|
33
|
-
return csp.
|
|
26
|
+
return csp.scriptDirective?.hashes ?? [];
|
|
34
27
|
}
|
|
35
28
|
function getStyleResources(csp) {
|
|
36
29
|
if (csp === true) {
|
|
@@ -38,6 +31,12 @@ function getStyleResources(csp) {
|
|
|
38
31
|
}
|
|
39
32
|
return csp.styleDirective?.resources ?? [];
|
|
40
33
|
}
|
|
34
|
+
function getStyleHashes(csp) {
|
|
35
|
+
if (csp === true) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
return csp.styleDirective?.hashes ?? [];
|
|
39
|
+
}
|
|
41
40
|
function getDirectives(settings) {
|
|
42
41
|
const { csp } = settings.config.security;
|
|
43
42
|
if (!shouldTrackCspHashes(csp)) {
|
|
@@ -13,6 +13,51 @@ export declare const cspAlgorithmSchema: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
|
13
13
|
}>>>;
|
|
14
14
|
export declare const cspHashSchema: z.ZodCustom<`sha256-${string}` | `sha384-${string}` | `sha512-${string}`, `sha256-${string}` | `sha384-${string}` | `sha512-${string}`>;
|
|
15
15
|
export type CspHash = z.infer<typeof cspHashSchema>;
|
|
16
|
+
/**
|
|
17
|
+
* The scope a resource or hash applies to:
|
|
18
|
+
* - `default`: the generic `script-src`/`style-src` directive (default behavior).
|
|
19
|
+
* - `element`: the `script-src-elem`/`style-src-elem` directive (`<script>`, `<style>`, `<link rel="stylesheet">`).
|
|
20
|
+
* - `attribute`: the `script-src-attr`/`style-src-attr` directive (inline event handlers and inline `style` attributes).
|
|
21
|
+
*/
|
|
22
|
+
export declare const CSP_KINDS: readonly ["element", "attribute", "default"];
|
|
23
|
+
export type CspKind = (typeof CSP_KINDS)[number];
|
|
24
|
+
export declare const cspKindSchema: z.ZodEnum<{
|
|
25
|
+
default: "default";
|
|
26
|
+
attribute: "attribute";
|
|
27
|
+
element: "element";
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* A `script-src`/`style-src` resource. A bare string targets `script-src`/`style-src` (the same as
|
|
31
|
+
* `kind: 'default'`). Use the object form with an explicit `kind` to target a more specific directive.
|
|
32
|
+
*/
|
|
33
|
+
export type CspResourceEntry = string | {
|
|
34
|
+
resource: string;
|
|
35
|
+
kind: CspKind;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* A `script-src`/`style-src` hash. A bare hash (a string) targets `script-src`/`style-src` (the same as
|
|
39
|
+
* `kind: 'default'`). Use the object form with an explicit `kind` to target a more specific directive.
|
|
40
|
+
*/
|
|
41
|
+
export type CspHashEntry = CspHash | {
|
|
42
|
+
hash: CspHash;
|
|
43
|
+
kind: CspKind;
|
|
44
|
+
};
|
|
45
|
+
export declare const cspResourceEntrySchema: z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
46
|
+
resource: z.ZodString;
|
|
47
|
+
kind: z.ZodEnum<{
|
|
48
|
+
default: "default";
|
|
49
|
+
attribute: "attribute";
|
|
50
|
+
element: "element";
|
|
51
|
+
}>;
|
|
52
|
+
}, z.core.$strip>]>;
|
|
53
|
+
export declare const cspHashEntrySchema: z.ZodUnion<readonly [z.ZodCustom<`sha256-${string}` | `sha384-${string}` | `sha512-${string}`, `sha256-${string}` | `sha384-${string}` | `sha512-${string}`>, z.ZodObject<{
|
|
54
|
+
hash: z.ZodCustom<`sha256-${string}` | `sha384-${string}` | `sha512-${string}`, `sha256-${string}` | `sha384-${string}` | `sha512-${string}`>;
|
|
55
|
+
kind: z.ZodEnum<{
|
|
56
|
+
default: "default";
|
|
57
|
+
attribute: "attribute";
|
|
58
|
+
element: "element";
|
|
59
|
+
}>;
|
|
60
|
+
}, z.core.$strip>]>;
|
|
16
61
|
declare const ALLOWED_DIRECTIVES: readonly ["base-uri", "child-src", "connect-src", "default-src", "fenced-frame-src", "font-src", "form-action", "frame-ancestors", "frame-src", "img-src", "manifest-src", "media-src", "object-src", "referrer", "report-to", "report-uri", "require-trusted-types-for", "sandbox", "trusted-types", "upgrade-insecure-requests", "worker-src"];
|
|
17
62
|
type AllowedDirectives = (typeof ALLOWED_DIRECTIVES)[number];
|
|
18
63
|
export type CspDirective = `${AllowedDirectives}${string | undefined}`;
|
package/dist/core/csp/config.js
CHANGED
|
@@ -14,6 +14,44 @@ const cspHashSchema = z.custom((value) => {
|
|
|
14
14
|
return value.startsWith(allowedValue);
|
|
15
15
|
});
|
|
16
16
|
});
|
|
17
|
+
const CSP_KINDS = ["element", "attribute", "default"];
|
|
18
|
+
const cspKindSchema = z.enum(CSP_KINDS);
|
|
19
|
+
const ATTRIBUTE_ALLOWED_RESOURCES = [
|
|
20
|
+
"'none'",
|
|
21
|
+
"'unsafe-hashes'",
|
|
22
|
+
"'unsafe-inline'",
|
|
23
|
+
"'report-sample'"
|
|
24
|
+
];
|
|
25
|
+
const cspResourceEntrySchema = z.union([
|
|
26
|
+
z.string(),
|
|
27
|
+
z.object({
|
|
28
|
+
resource: z.string(),
|
|
29
|
+
kind: cspKindSchema
|
|
30
|
+
})
|
|
31
|
+
]).superRefine((value, ctx) => {
|
|
32
|
+
const resource = typeof value === "string" ? value : value.resource;
|
|
33
|
+
const kind = typeof value === "string" ? "default" : value.kind;
|
|
34
|
+
if (kind === "element" && resource === "'unsafe-hashes'") {
|
|
35
|
+
ctx.addIssue({
|
|
36
|
+
code: z.ZodIssueCode.custom,
|
|
37
|
+
message: `The source \`'unsafe-hashes'\` is not valid for \`element\` resources (it is rejected by \`script-src-elem\`/\`style-src-elem\`).`,
|
|
38
|
+
fatal: true
|
|
39
|
+
});
|
|
40
|
+
} else if (kind === "attribute" && !ATTRIBUTE_ALLOWED_RESOURCES.includes(resource)) {
|
|
41
|
+
ctx.addIssue({
|
|
42
|
+
code: z.ZodIssueCode.custom,
|
|
43
|
+
message: `The source \`${resource}\` is not valid for \`attribute\` resources. \`script-src-attr\`/\`style-src-attr\` only accept: ${ATTRIBUTE_ALLOWED_RESOURCES.join(", ")}.`,
|
|
44
|
+
fatal: true
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
const cspHashEntrySchema = z.union([
|
|
49
|
+
cspHashSchema,
|
|
50
|
+
z.object({
|
|
51
|
+
hash: cspHashSchema,
|
|
52
|
+
kind: cspKindSchema
|
|
53
|
+
})
|
|
54
|
+
]);
|
|
17
55
|
const ALLOWED_DIRECTIVES = [
|
|
18
56
|
"base-uri",
|
|
19
57
|
"child-src",
|
|
@@ -45,7 +83,7 @@ const allowedDirectivesSchema = z.custom((v) => typeof v === "string").superRefi
|
|
|
45
83
|
if (value.startsWith("script-src") || value.startsWith("style-src")) {
|
|
46
84
|
ctx.addIssue({
|
|
47
85
|
code: z.ZodIssueCode.custom,
|
|
48
|
-
message: `Directives \`script-src\` and \`style-src\` are not allowed in \`security.csp.directives\`. Please use \`security.csp.scriptDirective\` and \`security.csp.styleDirective\` instead.`,
|
|
86
|
+
message: `Directives \`script-src\` and \`style-src\` (including their \`-elem\`/\`-attr\` variants) are not allowed in \`security.csp.directives\`. Please use \`security.csp.scriptDirective\` and \`security.csp.styleDirective\` instead, scoping resources/hashes to the more specific directives with the \`kind\` option (\`"element"\` or \`"attribute"\`).`,
|
|
49
87
|
fatal: true
|
|
50
88
|
});
|
|
51
89
|
} else {
|
|
@@ -59,7 +97,11 @@ const allowedDirectivesSchema = z.custom((v) => typeof v === "string").superRefi
|
|
|
59
97
|
});
|
|
60
98
|
export {
|
|
61
99
|
ALGORITHMS,
|
|
100
|
+
CSP_KINDS,
|
|
62
101
|
allowedDirectivesSchema,
|
|
63
102
|
cspAlgorithmSchema,
|
|
64
|
-
|
|
103
|
+
cspHashEntrySchema,
|
|
104
|
+
cspHashSchema,
|
|
105
|
+
cspKindSchema,
|
|
106
|
+
cspResourceEntrySchema
|
|
65
107
|
};
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import type { SSRManifestCSP } from '../app/types.js';
|
|
2
|
-
import type { CspDirective } from './config.js';
|
|
2
|
+
import type { CspDirective, CspHash, CspHashEntry, CspKind, CspResourceEntry } from './config.js';
|
|
3
|
+
export declare function normalizeCspResourceEntry(entry: CspResourceEntry): {
|
|
4
|
+
resource: string;
|
|
5
|
+
kind: CspKind;
|
|
6
|
+
};
|
|
7
|
+
export declare function normalizeCspHashEntry(entry: CspHashEntry): {
|
|
8
|
+
hash: CspHash;
|
|
9
|
+
kind: CspKind;
|
|
10
|
+
};
|
|
11
|
+
/** The resolved sources of a single CSP directive. */
|
|
12
|
+
export type CspDirectiveSources = {
|
|
13
|
+
resources: string[];
|
|
14
|
+
hashes: string[];
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Groups a directive's `resources`/`hashes` entries by their `kind`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function partitionByKind(directive: {
|
|
20
|
+
resources: CspResourceEntry[];
|
|
21
|
+
hashes: CspHashEntry[];
|
|
22
|
+
}): Record<CspKind, CspDirectiveSources>;
|
|
3
23
|
/**
|
|
4
24
|
* `existingDirective` is something like `img-src 'self'`. Same as `newDirective`.
|
|
5
25
|
*
|
package/dist/core/csp/runtime.js
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
function normalizeCspResourceEntry(entry) {
|
|
2
|
+
if (typeof entry === "string") {
|
|
3
|
+
return { resource: entry, kind: "default" };
|
|
4
|
+
}
|
|
5
|
+
return { resource: entry.resource, kind: entry.kind ?? "default" };
|
|
6
|
+
}
|
|
7
|
+
function normalizeCspHashEntry(entry) {
|
|
8
|
+
if (typeof entry === "string") {
|
|
9
|
+
return { hash: entry, kind: "default" };
|
|
10
|
+
}
|
|
11
|
+
return { hash: entry.hash, kind: entry.kind ?? "default" };
|
|
12
|
+
}
|
|
13
|
+
function partitionByKind(directive) {
|
|
14
|
+
const groups = {
|
|
15
|
+
default: { resources: [], hashes: [] },
|
|
16
|
+
element: { resources: [], hashes: [] },
|
|
17
|
+
attribute: { resources: [], hashes: [] }
|
|
18
|
+
};
|
|
19
|
+
for (const entry of directive.resources) {
|
|
20
|
+
const { resource, kind } = normalizeCspResourceEntry(entry);
|
|
21
|
+
groups[kind].resources.push(resource);
|
|
22
|
+
}
|
|
23
|
+
for (const entry of directive.hashes) {
|
|
24
|
+
const { hash, kind } = normalizeCspHashEntry(entry);
|
|
25
|
+
groups[kind].hashes.push(hash);
|
|
26
|
+
}
|
|
27
|
+
return groups;
|
|
28
|
+
}
|
|
1
29
|
function deduplicateDirectiveValues(existingDirective, newDirective) {
|
|
2
30
|
const [directiveName, ...existingValues] = existingDirective.split(/\s+/).filter(Boolean);
|
|
3
31
|
const [newDirectiveName, ...newValues] = newDirective.split(/\s+/).filter(Boolean);
|
|
@@ -33,5 +61,8 @@ function pushDirective(directives, newDirective) {
|
|
|
33
61
|
}
|
|
34
62
|
export {
|
|
35
63
|
deduplicateDirectiveValues,
|
|
64
|
+
normalizeCspHashEntry,
|
|
65
|
+
normalizeCspResourceEntry,
|
|
66
|
+
partitionByKind,
|
|
36
67
|
pushDirective
|
|
37
68
|
};
|
package/dist/core/dev/dev.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import { performance } from "node:perf_hooks";
|
|
3
3
|
import colors from "piccolore";
|
|
4
4
|
import { gt, major, minor, patch } from "semver";
|
|
5
|
-
import { getDataStoreFile } from "../../content/
|
|
5
|
+
import { getDataStoreDir, getDataStoreFile } from "../../content/paths.js";
|
|
6
6
|
import { globalContentLayer } from "../../content/instance.js";
|
|
7
7
|
import { attachContentServerListeners } from "../../content/index.js";
|
|
8
8
|
import { MutableDataStore } from "../../content/mutable-data-store.js";
|
|
@@ -26,7 +26,7 @@ async function dev(inlineConfig) {
|
|
|
26
26
|
await telemetry.record([]);
|
|
27
27
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
28
28
|
const logger = restart.container.logger;
|
|
29
|
-
const currentVersion = "7.0
|
|
29
|
+
const currentVersion = "7.1.0";
|
|
30
30
|
const isPrerelease = currentVersion.includes("-");
|
|
31
31
|
if (!isPrerelease) {
|
|
32
32
|
try {
|
|
@@ -56,8 +56,13 @@ async function dev(inlineConfig) {
|
|
|
56
56
|
}
|
|
57
57
|
let store;
|
|
58
58
|
try {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
if (restart.container.settings.config.experimental.collectionStorage === "chunked") {
|
|
60
|
+
const dataStoreDir = getDataStoreDir(restart.container.settings, true);
|
|
61
|
+
store = await MutableDataStore.fromDir(dataStoreDir);
|
|
62
|
+
} else {
|
|
63
|
+
const dataStoreFile = getDataStoreFile(restart.container.settings, true);
|
|
64
|
+
store = await MutableDataStore.fromFile(dataStoreFile);
|
|
65
|
+
}
|
|
61
66
|
} catch (err) {
|
|
62
67
|
logger.error("content", err.message);
|
|
63
68
|
}
|
package/dist/core/dev/restart.js
CHANGED
|
@@ -12,7 +12,11 @@ import { collectErrorMetadata } from "../errors/dev/utils.js";
|
|
|
12
12
|
import { isAstroConfigZodError } from "../errors/errors.js";
|
|
13
13
|
import { createSafeError } from "../errors/index.js";
|
|
14
14
|
import { loadOrCreateNodeLogger } from "../logger/load.js";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
formatErrorMessage,
|
|
17
|
+
warnIfCspResourceFallbackShadowing,
|
|
18
|
+
warnIfCspWithShiki
|
|
19
|
+
} from "../messages/runtime.js";
|
|
16
20
|
import { createRoutesList } from "../routing/create-manifest.js";
|
|
17
21
|
import { createContainer } from "./container.js";
|
|
18
22
|
const configRE = /.*astro.config.(?:mjs|mts|cjs|cts|js|ts)$/;
|
|
@@ -46,6 +50,7 @@ async function restartContainerInPlace(container) {
|
|
|
46
50
|
try {
|
|
47
51
|
const { astroConfig } = await resolveConfig(inlineConfig, "dev", fs);
|
|
48
52
|
warnIfCspWithShiki(astroConfig, logger);
|
|
53
|
+
warnIfCspResourceFallbackShadowing(astroConfig, logger);
|
|
49
54
|
let settings = await createSettings(
|
|
50
55
|
astroConfig,
|
|
51
56
|
inlineConfig.logLevel,
|
|
@@ -100,6 +105,7 @@ async function createContainerWithAutomaticRestart({
|
|
|
100
105
|
const { userConfig, astroConfig } = await resolveConfig(inlineConfig ?? {}, "dev", fs);
|
|
101
106
|
const logger = await loadOrCreateNodeLogger(astroConfig, inlineConfig ?? {});
|
|
102
107
|
warnIfCspWithShiki(astroConfig, logger);
|
|
108
|
+
warnIfCspResourceFallbackShadowing(astroConfig, logger);
|
|
103
109
|
telemetry.record(eventCliSession("dev", userConfig));
|
|
104
110
|
const settings = await createSettings(
|
|
105
111
|
astroConfig,
|
|
@@ -122,7 +122,13 @@ const getTypeOrLiteralMsg = (error) => {
|
|
|
122
122
|
const prefix = (key, msg) => key.length ? `**${key}**: ${msg}` : msg;
|
|
123
123
|
const unionExpectedVals = (expectedVals) => [...expectedVals].map((expectedVal) => stringify(expectedVal)).join(" | ");
|
|
124
124
|
const flattenErrorPath = (errorPath) => errorPath.join(".");
|
|
125
|
-
const stringify = (val) =>
|
|
125
|
+
const stringify = (val) => {
|
|
126
|
+
const json = JSON.stringify(val, null, 1);
|
|
127
|
+
if (json === void 0) {
|
|
128
|
+
return String(val);
|
|
129
|
+
}
|
|
130
|
+
return json.split(newlinePlusWhitespace).join(" ");
|
|
131
|
+
};
|
|
126
132
|
const newlinePlusWhitespace = /\n\s*/;
|
|
127
133
|
const leadingPeriod = /^\./;
|
|
128
134
|
export {
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
pipelineSymbol,
|
|
17
17
|
responseSentSymbol
|
|
18
18
|
} from "../constants.js";
|
|
19
|
-
import { pushDirective } from "../csp/runtime.js";
|
|
19
|
+
import { normalizeCspResourceEntry, pushDirective } from "../csp/runtime.js";
|
|
20
20
|
import { generateCspDigest } from "../encryption.js";
|
|
21
21
|
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
22
22
|
import {
|
|
@@ -304,12 +304,26 @@ class FetchState {
|
|
|
304
304
|
cspDestination: manifest.csp?.cspDestination ?? (routeData.prerender ? "meta" : "header"),
|
|
305
305
|
shouldInjectCspMetaTags,
|
|
306
306
|
cspAlgorithm,
|
|
307
|
+
directives: manifest.csp?.directives ? [...manifest.csp.directives] : [],
|
|
308
|
+
// Deprecated flat fields, kept for back-compat. Seeded from the manifest; the runtime CSP
|
|
309
|
+
// API updates the structured `scriptDirective`/`styleDirective` below (which the renderer
|
|
310
|
+
// reads), not these.
|
|
307
311
|
scriptHashes: manifest.csp?.scriptHashes ? [...manifest.csp.scriptHashes] : [],
|
|
308
312
|
scriptResources: manifest.csp?.scriptResources ? [...manifest.csp.scriptResources] : [],
|
|
309
313
|
styleHashes: manifest.csp?.styleHashes ? [...manifest.csp.styleHashes] : [],
|
|
310
314
|
styleResources: manifest.csp?.styleResources ? [...manifest.csp.styleResources] : [],
|
|
311
|
-
directives: manifest.csp?.directives ? [...manifest.csp.directives] : [],
|
|
312
315
|
isStrictDynamic: manifest.csp?.isStrictDynamic ?? false,
|
|
316
|
+
// Structured fields (source of truth). Arrays are cloned so per-request runtime inserts
|
|
317
|
+
// don't mutate the shared manifest.
|
|
318
|
+
scriptDirective: {
|
|
319
|
+
resources: manifest.csp?.scriptDirective ? [...manifest.csp.scriptDirective.resources] : [],
|
|
320
|
+
hashes: manifest.csp?.scriptDirective ? [...manifest.csp.scriptDirective.hashes] : [],
|
|
321
|
+
strictDynamic: manifest.csp?.scriptDirective?.strictDynamic ?? false
|
|
322
|
+
},
|
|
323
|
+
styleDirective: {
|
|
324
|
+
resources: manifest.csp?.styleDirective ? [...manifest.csp.styleDirective.resources] : [],
|
|
325
|
+
hashes: manifest.csp?.styleDirective ? [...manifest.csp.styleDirective.hashes] : []
|
|
326
|
+
},
|
|
313
327
|
internalFetchHeaders: manifest.internalFetchHeaders
|
|
314
328
|
};
|
|
315
329
|
this.result = result;
|
|
@@ -451,23 +465,51 @@ class FetchState {
|
|
|
451
465
|
}
|
|
452
466
|
return void 0;
|
|
453
467
|
}
|
|
468
|
+
const warnedFallback = /* @__PURE__ */ new Set();
|
|
469
|
+
const warnFallback = (family, kind) => {
|
|
470
|
+
if (kind === "default" || !state.result) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
const directive = family === "script" ? state.result.scriptDirective : state.result.styleDirective;
|
|
474
|
+
const defaultResources = directive.resources.map(normalizeCspResourceEntry).filter((entry) => entry.kind === "default").map((entry) => entry.resource);
|
|
475
|
+
if (defaultResources.length === 0) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
const key = `${family}:${kind}`;
|
|
479
|
+
if (warnedFallback.has(key)) {
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
warnedFallback.add(key);
|
|
483
|
+
const general = `${family}-src`;
|
|
484
|
+
const specific = `${general}-${kind === "element" ? "elem" : "attr"}`;
|
|
485
|
+
pipeline.logger.warn(
|
|
486
|
+
"csp",
|
|
487
|
+
`A resource was added to \`${specific}\`, but \`${general}\` also defines custom resources (${defaultResources.join(
|
|
488
|
+
" "
|
|
489
|
+
)}). 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.`
|
|
490
|
+
);
|
|
491
|
+
};
|
|
454
492
|
return {
|
|
455
493
|
insertDirective(payload) {
|
|
456
494
|
if (state.result) {
|
|
457
495
|
state.result.directives = pushDirective(state.result.directives, payload);
|
|
458
496
|
}
|
|
459
497
|
},
|
|
460
|
-
insertScriptResource(
|
|
461
|
-
state.result
|
|
498
|
+
insertScriptResource(payload) {
|
|
499
|
+
if (!state.result) return;
|
|
500
|
+
warnFallback("script", normalizeCspResourceEntry(payload).kind);
|
|
501
|
+
state.result.scriptDirective.resources.push(payload);
|
|
462
502
|
},
|
|
463
|
-
insertStyleResource(
|
|
464
|
-
state.result
|
|
503
|
+
insertStyleResource(payload) {
|
|
504
|
+
if (!state.result) return;
|
|
505
|
+
warnFallback("style", normalizeCspResourceEntry(payload).kind);
|
|
506
|
+
state.result.styleDirective.resources.push(payload);
|
|
465
507
|
},
|
|
466
|
-
insertStyleHash(
|
|
467
|
-
state.result?.
|
|
508
|
+
insertStyleHash(payload) {
|
|
509
|
+
state.result?.styleDirective.hashes.push(payload);
|
|
468
510
|
},
|
|
469
|
-
insertScriptHash(
|
|
470
|
-
state.result?.
|
|
511
|
+
insertScriptHash(payload) {
|
|
512
|
+
state.result?.scriptDirective.hashes.push(payload);
|
|
471
513
|
}
|
|
472
514
|
};
|
|
473
515
|
}
|
|
@@ -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;
|