astro 4.11.4 → 4.11.6
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/@types/astro.d.ts +32 -2
- package/dist/actions/runtime/utils.d.ts +10 -0
- package/dist/actions/runtime/virtual/server.d.ts +9 -8
- package/dist/actions/runtime/virtual/server.js +3 -8
- package/dist/actions/runtime/virtual/shared.d.ts +4 -4
- package/dist/actions/runtime/virtual/shared.js +16 -0
- package/dist/core/app/index.js +1 -1
- package/dist/core/build/plugins/plugin-pages.js +2 -2
- package/dist/core/build/plugins/plugin-prerender.js +1 -1
- package/dist/core/config/schema.d.ts +25 -2
- package/dist/core/config/schema.js +6 -2
- package/dist/core/constants.js +1 -1
- package/dist/core/create-vite.js +2 -11
- package/dist/core/dev/container.js +3 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/errors/errors-data.d.ts +1 -1
- package/dist/core/errors/errors-data.js +2 -2
- package/dist/core/messages.js +2 -2
- package/dist/env/schema.d.ts +1 -1
- package/dist/env/schema.js +6 -7
- package/dist/env/validators.d.ts +2 -2
- package/dist/env/validators.js +82 -57
- package/dist/env/vite-plugin-env.js +27 -13
- package/dist/runtime/client/dev-toolbar/apps/audit/rules/a11y.js +2 -1
- package/dist/runtime/server/render/util.js +11 -5
- package/package.json +23 -21
package/dist/@types/astro.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { MarkdownHeading, MarkdownVFile, RehypePlugins, RemarkPlugins, Rema
|
|
|
4
4
|
import type * as babel from '@babel/core';
|
|
5
5
|
import type * as rollup from 'rollup';
|
|
6
6
|
import type * as vite from 'vite';
|
|
7
|
-
import type {
|
|
7
|
+
import type { ActionAccept, ActionClient, ActionInputSchema } from '../actions/runtime/virtual/server.js';
|
|
8
8
|
import type { RemotePattern } from '../assets/utils/remotePattern.js';
|
|
9
9
|
import type { AssetsPrefix, SerializedSSRManifest } from '../core/app/types.js';
|
|
10
10
|
import type { PageBuildData } from '../core/build/types.js';
|
|
@@ -2025,6 +2025,36 @@ export interface AstroUserConfig {
|
|
|
2025
2025
|
* ```
|
|
2026
2026
|
*/
|
|
2027
2027
|
schema?: EnvSchema;
|
|
2028
|
+
/**
|
|
2029
|
+
* @docs
|
|
2030
|
+
* @name experimental.env.validateSecrets
|
|
2031
|
+
* @kind h4
|
|
2032
|
+
* @type {boolean}
|
|
2033
|
+
* @default `false`
|
|
2034
|
+
* @version 4.11.6
|
|
2035
|
+
* @description
|
|
2036
|
+
*
|
|
2037
|
+
* Whether or not to validate secrets on the server when starting the dev server or running a build.
|
|
2038
|
+
*
|
|
2039
|
+
* By default, only public variables are validated on the server when starting the dev server or a build, and private variables are validated at runtime only. If enabled, private variables will also be checked on start. This is useful in some continuous integration (CI) pipelines to make sure all your secrets are correctly set before deploying.
|
|
2040
|
+
*
|
|
2041
|
+
* ```js
|
|
2042
|
+
* // astro.config.mjs
|
|
2043
|
+
* import { defineConfig, envField } from "astro/config"
|
|
2044
|
+
*
|
|
2045
|
+
* export default defineConfig({
|
|
2046
|
+
* experimental: {
|
|
2047
|
+
* env: {
|
|
2048
|
+
* schema: {
|
|
2049
|
+
* // ...
|
|
2050
|
+
* },
|
|
2051
|
+
* validateSecrets: true
|
|
2052
|
+
* }
|
|
2053
|
+
* }
|
|
2054
|
+
* })
|
|
2055
|
+
* ```
|
|
2056
|
+
*/
|
|
2057
|
+
validateSecrets?: boolean;
|
|
2028
2058
|
};
|
|
2029
2059
|
};
|
|
2030
2060
|
}
|
|
@@ -2492,7 +2522,7 @@ interface AstroSharedContext<Props extends Record<string, any> = Record<string,
|
|
|
2492
2522
|
/**
|
|
2493
2523
|
* Get action result on the server when using a form POST.
|
|
2494
2524
|
*/
|
|
2495
|
-
getActionResult: <TAccept extends
|
|
2525
|
+
getActionResult: <TAccept extends ActionAccept, TInputSchema extends ActionInputSchema<TAccept>, TAction extends ActionClient<unknown, TAccept, TInputSchema>>(action: TAction) => Awaited<ReturnType<TAction['safe']>> | undefined;
|
|
2496
2526
|
/**
|
|
2497
2527
|
* Route parameters for this request if this is a dynamic route.
|
|
2498
2528
|
*/
|
|
@@ -7,3 +7,13 @@ export type MaybePromise<T> = T | Promise<T>;
|
|
|
7
7
|
* the user's `src/actions/index.ts` file at build-time.
|
|
8
8
|
*/
|
|
9
9
|
export declare function getAction(path: string): Promise<((param: unknown) => MaybePromise<unknown>) | undefined>;
|
|
10
|
+
/**
|
|
11
|
+
* Used to preserve the input schema type in the error object.
|
|
12
|
+
* This allows for type inference on the `fields` property
|
|
13
|
+
* when type narrowed to an `ActionInputError`.
|
|
14
|
+
*
|
|
15
|
+
* Example: Action has an input schema of `{ name: z.string() }`.
|
|
16
|
+
* When calling the action and checking `isInputError(result.error)`,
|
|
17
|
+
* `result.error.fields` will be typed with the `name` field.
|
|
18
|
+
*/
|
|
19
|
+
export type ErrorInferenceObject = Record<string, any>;
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { type ActionAPIContext, getApiContext as _getApiContext } from '../store.js';
|
|
3
|
-
import {
|
|
4
|
-
import { type
|
|
3
|
+
import type { ErrorInferenceObject, MaybePromise } from '../utils.js';
|
|
4
|
+
import { type SafeResult } from './shared.js';
|
|
5
5
|
export * from './shared.js';
|
|
6
6
|
export { z } from 'zod';
|
|
7
7
|
/** @deprecated Access context from the second `handler()` parameter. */
|
|
8
8
|
export declare const getApiContext: typeof _getApiContext;
|
|
9
|
-
export type
|
|
10
|
-
export type
|
|
11
|
-
type
|
|
12
|
-
export type
|
|
9
|
+
export type ActionAccept = 'form' | 'json';
|
|
10
|
+
export type ActionInputSchema<T extends ActionAccept | undefined> = T extends 'form' ? z.AnyZodObject | z.ZodType<FormData> : z.ZodType;
|
|
11
|
+
export type ActionHandler<TInputSchema, TOutput> = TInputSchema extends z.ZodType ? (input: z.infer<TInputSchema>, context: ActionAPIContext) => MaybePromise<TOutput> : (input: any, context: ActionAPIContext) => MaybePromise<TOutput>;
|
|
12
|
+
export type ActionReturnType<T extends ActionHandler<any, any>> = Awaited<ReturnType<T>>;
|
|
13
|
+
export type ActionClient<TOutput, TAccept extends ActionAccept | undefined, TInputSchema extends ActionInputSchema<TAccept> | undefined> = TInputSchema extends z.ZodType ? ((input: TAccept extends 'form' ? FormData : z.input<TInputSchema>) => Promise<Awaited<TOutput>>) & {
|
|
13
14
|
safe: (input: TAccept extends 'form' ? FormData : z.input<TInputSchema>) => Promise<SafeResult<z.input<TInputSchema> extends ErrorInferenceObject ? z.input<TInputSchema> : ErrorInferenceObject, Awaited<TOutput>>>;
|
|
14
15
|
} : ((input?: any) => Promise<Awaited<TOutput>>) & {
|
|
15
16
|
safe: (input?: any) => Promise<SafeResult<never, Awaited<TOutput>>>;
|
|
16
17
|
};
|
|
17
|
-
export declare function defineAction<TOutput, TAccept extends
|
|
18
|
+
export declare function defineAction<TOutput, TAccept extends ActionAccept | undefined = undefined, TInputSchema extends ActionInputSchema<ActionAccept> | undefined = TAccept extends 'form' ? z.ZodType<FormData> : undefined>({ accept, input: inputSchema, handler, }: {
|
|
18
19
|
input?: TInputSchema;
|
|
19
20
|
accept?: TAccept;
|
|
20
|
-
handler:
|
|
21
|
+
handler: ActionHandler<TInputSchema, TOutput>;
|
|
21
22
|
}): ActionClient<TOutput, TAccept, TInputSchema>;
|
|
22
23
|
/** Transform form data to an object based on a Zod schema. */
|
|
23
24
|
export declare function formDataToObject<T extends z.AnyZodObject>(formData: FormData, schema: T): Record<string, unknown>;
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { getApiContext as _getApiContext } from "../store.js";
|
|
3
|
-
import {} from "
|
|
4
|
-
import {
|
|
5
|
-
ActionError,
|
|
6
|
-
ActionInputError,
|
|
7
|
-
callSafely
|
|
8
|
-
} from "./shared.js";
|
|
3
|
+
import { ActionError, ActionInputError, callSafely } from "./shared.js";
|
|
9
4
|
export * from "./shared.js";
|
|
10
5
|
import { z as z2 } from "zod";
|
|
11
6
|
const getApiContext = _getApiContext;
|
|
@@ -58,8 +53,8 @@ function formDataToObject(formData, schema) {
|
|
|
58
53
|
const obj = {};
|
|
59
54
|
for (const [key, baseValidator] of Object.entries(schema.shape)) {
|
|
60
55
|
let validator = baseValidator;
|
|
61
|
-
|
|
62
|
-
validator =
|
|
56
|
+
while (validator instanceof z.ZodOptional || validator instanceof z.ZodNullable) {
|
|
57
|
+
validator = validator._def.innerType;
|
|
63
58
|
}
|
|
64
59
|
if (validator instanceof z.ZodBoolean) {
|
|
65
60
|
obj[key] = formData.has(key);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { z } from 'zod';
|
|
2
|
-
import type { MaybePromise } from '../utils.js';
|
|
3
|
-
|
|
4
|
-
export type
|
|
2
|
+
import type { ErrorInferenceObject, MaybePromise } from '../utils.js';
|
|
3
|
+
export declare const ACTION_ERROR_CODES: readonly ["BAD_REQUEST", "UNAUTHORIZED", "FORBIDDEN", "NOT_FOUND", "TIMEOUT", "CONFLICT", "PRECONDITION_FAILED", "PAYLOAD_TOO_LARGE", "UNSUPPORTED_MEDIA_TYPE", "UNPROCESSABLE_CONTENT", "TOO_MANY_REQUESTS", "CLIENT_CLOSED_REQUEST", "INTERNAL_SERVER_ERROR"];
|
|
4
|
+
export type ActionErrorCode = (typeof ACTION_ERROR_CODES)[number];
|
|
5
5
|
export declare class ActionError<T extends ErrorInferenceObject = ErrorInferenceObject> extends Error {
|
|
6
6
|
type: string;
|
|
7
7
|
code: ActionErrorCode;
|
|
@@ -16,6 +16,7 @@ export declare class ActionError<T extends ErrorInferenceObject = ErrorInference
|
|
|
16
16
|
static fromResponse(res: Response): Promise<ActionError<ErrorInferenceObject>>;
|
|
17
17
|
}
|
|
18
18
|
export declare function isInputError<T extends ErrorInferenceObject>(error?: ActionError<T>): error is ActionInputError<T>;
|
|
19
|
+
export declare function isInputError(error?: unknown): error is ActionInputError<ErrorInferenceObject>;
|
|
19
20
|
export type SafeResult<TInput extends ErrorInferenceObject, TOutput> = {
|
|
20
21
|
data: TOutput;
|
|
21
22
|
error: undefined;
|
|
@@ -35,4 +36,3 @@ export declare function getActionProps<T extends (args: FormData) => MaybePromis
|
|
|
35
36
|
readonly name: "_astroAction";
|
|
36
37
|
readonly value: string;
|
|
37
38
|
};
|
|
38
|
-
export {};
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
const ACTION_ERROR_CODES = [
|
|
2
|
+
"BAD_REQUEST",
|
|
3
|
+
"UNAUTHORIZED",
|
|
4
|
+
"FORBIDDEN",
|
|
5
|
+
"NOT_FOUND",
|
|
6
|
+
"TIMEOUT",
|
|
7
|
+
"CONFLICT",
|
|
8
|
+
"PRECONDITION_FAILED",
|
|
9
|
+
"PAYLOAD_TOO_LARGE",
|
|
10
|
+
"UNSUPPORTED_MEDIA_TYPE",
|
|
11
|
+
"UNPROCESSABLE_CONTENT",
|
|
12
|
+
"TOO_MANY_REQUESTS",
|
|
13
|
+
"CLIENT_CLOSED_REQUEST",
|
|
14
|
+
"INTERNAL_SERVER_ERROR"
|
|
15
|
+
];
|
|
1
16
|
const codeToStatusMap = {
|
|
2
17
|
// Implemented from tRPC error code table
|
|
3
18
|
// https://trpc.io/docs/server/error-handling#error-codes
|
|
@@ -103,6 +118,7 @@ function getActionProps(action) {
|
|
|
103
118
|
};
|
|
104
119
|
}
|
|
105
120
|
export {
|
|
121
|
+
ACTION_ERROR_CODES,
|
|
106
122
|
ActionError,
|
|
107
123
|
ActionInputError,
|
|
108
124
|
callSafely,
|
package/dist/core/app/index.js
CHANGED
|
@@ -216,9 +216,9 @@ class App {
|
|
|
216
216
|
}
|
|
217
217
|
const pathname = this.#getPathnameFromRequest(request);
|
|
218
218
|
const defaultStatus = this.#getDefaultStatusCode(routeData, pathname);
|
|
219
|
-
const mod = await this.#pipeline.getModuleForRoute(routeData);
|
|
220
219
|
let response;
|
|
221
220
|
try {
|
|
221
|
+
const mod = await this.#pipeline.getModuleForRoute(routeData);
|
|
222
222
|
const renderContext = RenderContext.create({
|
|
223
223
|
pipeline: this.#pipeline,
|
|
224
224
|
locals,
|
|
@@ -37,8 +37,8 @@ function vitePluginPages(opts, internals) {
|
|
|
37
37
|
for (const pageData of pageDatas) {
|
|
38
38
|
const resolvedPage = await this.resolve(pageData.moduleSpecifier);
|
|
39
39
|
if (resolvedPage) {
|
|
40
|
-
imports.push(`
|
|
41
|
-
exports.push(`export
|
|
40
|
+
imports.push(`import * as _page from ${JSON.stringify(pageData.moduleSpecifier)};`);
|
|
41
|
+
exports.push(`export const page = () => _page`);
|
|
42
42
|
imports.push(`import { renderers } from "${RENDERERS_MODULE_ID}";`);
|
|
43
43
|
exports.push(`export { renderers };`);
|
|
44
44
|
return `${imports.join("\n")}${exports.join("\n")}`;
|
|
@@ -26,7 +26,7 @@ function getNonPrerenderOnlyChunks(bundle, internals) {
|
|
|
26
26
|
const prerenderOnlyEntryChunks = /* @__PURE__ */ new Set();
|
|
27
27
|
const nonPrerenderOnlyEntryChunks = /* @__PURE__ */ new Set();
|
|
28
28
|
for (const chunk of chunks) {
|
|
29
|
-
if (chunk.type === "chunk" &&
|
|
29
|
+
if (chunk.type === "chunk" && chunk.isEntry) {
|
|
30
30
|
if (chunk.facadeModuleId?.startsWith(ASTRO_PAGE_RESOLVED_MODULE_ID)) {
|
|
31
31
|
const pageDatas = getPagesFromVirtualModulePageName(
|
|
32
32
|
internals,
|
|
@@ -58,6 +58,9 @@ export declare const ASTRO_CONFIG_DEFAULTS: {
|
|
|
58
58
|
clientPrerender: false;
|
|
59
59
|
globalRoutePriority: false;
|
|
60
60
|
rewriting: false;
|
|
61
|
+
env: {
|
|
62
|
+
validateSecrets: false;
|
|
63
|
+
};
|
|
61
64
|
};
|
|
62
65
|
};
|
|
63
66
|
export declare const AstroConfigSchema: z.ZodObject<{
|
|
@@ -398,7 +401,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
398
401
|
globalRoutePriority: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
399
402
|
rewriting: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
400
403
|
env: z.ZodOptional<z.ZodObject<{
|
|
401
|
-
schema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodIntersection<z.ZodUnion<[z.ZodObject<{
|
|
404
|
+
schema: z.ZodOptional<z.ZodRecord<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, z.ZodIntersection<z.ZodUnion<[z.ZodObject<{
|
|
402
405
|
context: z.ZodLiteral<"client">;
|
|
403
406
|
access: z.ZodLiteral<"public">;
|
|
404
407
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -523,7 +526,9 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
523
526
|
default?: string | undefined;
|
|
524
527
|
optional?: boolean | undefined;
|
|
525
528
|
}>]>>>>;
|
|
529
|
+
validateSecrets: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
526
530
|
}, "strict", z.ZodTypeAny, {
|
|
531
|
+
validateSecrets: boolean;
|
|
527
532
|
schema?: Record<string, ({
|
|
528
533
|
context: "client";
|
|
529
534
|
access: "public";
|
|
@@ -564,6 +569,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
564
569
|
optional?: boolean | undefined;
|
|
565
570
|
})> | undefined;
|
|
566
571
|
}, {
|
|
572
|
+
validateSecrets?: boolean | undefined;
|
|
567
573
|
schema?: Record<string, ({
|
|
568
574
|
context: "client";
|
|
569
575
|
access: "public";
|
|
@@ -613,6 +619,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
613
619
|
globalRoutePriority: boolean;
|
|
614
620
|
rewriting: boolean;
|
|
615
621
|
env?: {
|
|
622
|
+
validateSecrets: boolean;
|
|
616
623
|
schema?: Record<string, ({
|
|
617
624
|
context: "client";
|
|
618
625
|
access: "public";
|
|
@@ -662,6 +669,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
662
669
|
globalRoutePriority?: boolean | undefined;
|
|
663
670
|
rewriting?: boolean | undefined;
|
|
664
671
|
env?: {
|
|
672
|
+
validateSecrets?: boolean | undefined;
|
|
665
673
|
schema?: Record<string, ({
|
|
666
674
|
context: "client";
|
|
667
675
|
access: "public";
|
|
@@ -788,6 +796,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
788
796
|
globalRoutePriority: boolean;
|
|
789
797
|
rewriting: boolean;
|
|
790
798
|
env?: {
|
|
799
|
+
validateSecrets: boolean;
|
|
791
800
|
schema?: Record<string, ({
|
|
792
801
|
context: "client";
|
|
793
802
|
access: "public";
|
|
@@ -950,6 +959,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
950
959
|
globalRoutePriority?: boolean | undefined;
|
|
951
960
|
rewriting?: boolean | undefined;
|
|
952
961
|
env?: {
|
|
962
|
+
validateSecrets?: boolean | undefined;
|
|
953
963
|
schema?: Record<string, ({
|
|
954
964
|
context: "client";
|
|
955
965
|
access: "public";
|
|
@@ -1332,7 +1342,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
1332
1342
|
globalRoutePriority: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1333
1343
|
rewriting: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1334
1344
|
env: z.ZodOptional<z.ZodObject<{
|
|
1335
|
-
schema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodIntersection<z.ZodUnion<[z.ZodObject<{
|
|
1345
|
+
schema: z.ZodOptional<z.ZodRecord<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, z.ZodIntersection<z.ZodUnion<[z.ZodObject<{
|
|
1336
1346
|
context: z.ZodLiteral<"client">;
|
|
1337
1347
|
access: z.ZodLiteral<"public">;
|
|
1338
1348
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -1457,7 +1467,9 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
1457
1467
|
default?: string | undefined;
|
|
1458
1468
|
optional?: boolean | undefined;
|
|
1459
1469
|
}>]>>>>;
|
|
1470
|
+
validateSecrets: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1460
1471
|
}, "strict", z.ZodTypeAny, {
|
|
1472
|
+
validateSecrets: boolean;
|
|
1461
1473
|
schema?: Record<string, ({
|
|
1462
1474
|
context: "client";
|
|
1463
1475
|
access: "public";
|
|
@@ -1498,6 +1510,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
1498
1510
|
optional?: boolean | undefined;
|
|
1499
1511
|
})> | undefined;
|
|
1500
1512
|
}, {
|
|
1513
|
+
validateSecrets?: boolean | undefined;
|
|
1501
1514
|
schema?: Record<string, ({
|
|
1502
1515
|
context: "client";
|
|
1503
1516
|
access: "public";
|
|
@@ -1547,6 +1560,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
1547
1560
|
globalRoutePriority: boolean;
|
|
1548
1561
|
rewriting: boolean;
|
|
1549
1562
|
env?: {
|
|
1563
|
+
validateSecrets: boolean;
|
|
1550
1564
|
schema?: Record<string, ({
|
|
1551
1565
|
context: "client";
|
|
1552
1566
|
access: "public";
|
|
@@ -1596,6 +1610,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
1596
1610
|
globalRoutePriority?: boolean | undefined;
|
|
1597
1611
|
rewriting?: boolean | undefined;
|
|
1598
1612
|
env?: {
|
|
1613
|
+
validateSecrets?: boolean | undefined;
|
|
1599
1614
|
schema?: Record<string, ({
|
|
1600
1615
|
context: "client";
|
|
1601
1616
|
access: "public";
|
|
@@ -1797,6 +1812,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
1797
1812
|
globalRoutePriority: boolean;
|
|
1798
1813
|
rewriting: boolean;
|
|
1799
1814
|
env?: {
|
|
1815
|
+
validateSecrets: boolean;
|
|
1800
1816
|
schema?: Record<string, ({
|
|
1801
1817
|
context: "client";
|
|
1802
1818
|
access: "public";
|
|
@@ -1959,6 +1975,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
1959
1975
|
globalRoutePriority?: boolean | undefined;
|
|
1960
1976
|
rewriting?: boolean | undefined;
|
|
1961
1977
|
env?: {
|
|
1978
|
+
validateSecrets?: boolean | undefined;
|
|
1962
1979
|
schema?: Record<string, ({
|
|
1963
1980
|
context: "client";
|
|
1964
1981
|
access: "public";
|
|
@@ -2086,6 +2103,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
2086
2103
|
globalRoutePriority: boolean;
|
|
2087
2104
|
rewriting: boolean;
|
|
2088
2105
|
env?: {
|
|
2106
|
+
validateSecrets: boolean;
|
|
2089
2107
|
schema?: Record<string, ({
|
|
2090
2108
|
context: "client";
|
|
2091
2109
|
access: "public";
|
|
@@ -2248,6 +2266,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
2248
2266
|
globalRoutePriority?: boolean | undefined;
|
|
2249
2267
|
rewriting?: boolean | undefined;
|
|
2250
2268
|
env?: {
|
|
2269
|
+
validateSecrets?: boolean | undefined;
|
|
2251
2270
|
schema?: Record<string, ({
|
|
2252
2271
|
context: "client";
|
|
2253
2272
|
access: "public";
|
|
@@ -2375,6 +2394,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
2375
2394
|
globalRoutePriority: boolean;
|
|
2376
2395
|
rewriting: boolean;
|
|
2377
2396
|
env?: {
|
|
2397
|
+
validateSecrets: boolean;
|
|
2378
2398
|
schema?: Record<string, ({
|
|
2379
2399
|
context: "client";
|
|
2380
2400
|
access: "public";
|
|
@@ -2537,6 +2557,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
2537
2557
|
globalRoutePriority?: boolean | undefined;
|
|
2538
2558
|
rewriting?: boolean | undefined;
|
|
2539
2559
|
env?: {
|
|
2560
|
+
validateSecrets?: boolean | undefined;
|
|
2540
2561
|
schema?: Record<string, ({
|
|
2541
2562
|
context: "client";
|
|
2542
2563
|
access: "public";
|
|
@@ -2664,6 +2685,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
2664
2685
|
globalRoutePriority: boolean;
|
|
2665
2686
|
rewriting: boolean;
|
|
2666
2687
|
env?: {
|
|
2688
|
+
validateSecrets: boolean;
|
|
2667
2689
|
schema?: Record<string, ({
|
|
2668
2690
|
context: "client";
|
|
2669
2691
|
access: "public";
|
|
@@ -2826,6 +2848,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
2826
2848
|
globalRoutePriority?: boolean | undefined;
|
|
2827
2849
|
rewriting?: boolean | undefined;
|
|
2828
2850
|
env?: {
|
|
2851
|
+
validateSecrets?: boolean | undefined;
|
|
2829
2852
|
schema?: Record<string, ({
|
|
2830
2853
|
context: "client";
|
|
2831
2854
|
access: "public";
|
|
@@ -47,7 +47,10 @@ const ASTRO_CONFIG_DEFAULTS = {
|
|
|
47
47
|
contentCollectionJsonSchema: false,
|
|
48
48
|
clientPrerender: false,
|
|
49
49
|
globalRoutePriority: false,
|
|
50
|
-
rewriting: false
|
|
50
|
+
rewriting: false,
|
|
51
|
+
env: {
|
|
52
|
+
validateSecrets: false
|
|
53
|
+
}
|
|
51
54
|
}
|
|
52
55
|
};
|
|
53
56
|
const AstroConfigSchema = z.object({
|
|
@@ -328,7 +331,8 @@ const AstroConfigSchema = z.object({
|
|
|
328
331
|
globalRoutePriority: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.globalRoutePriority),
|
|
329
332
|
rewriting: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.rewriting),
|
|
330
333
|
env: z.object({
|
|
331
|
-
schema: EnvSchema.optional()
|
|
334
|
+
schema: EnvSchema.optional(),
|
|
335
|
+
validateSecrets: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.env.validateSecrets)
|
|
332
336
|
}).strict().optional()
|
|
333
337
|
}).strict(
|
|
334
338
|
`Invalid or outdated experimental feature.
|
package/dist/core/constants.js
CHANGED
package/dist/core/create-vite.js
CHANGED
|
@@ -90,17 +90,8 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
|
|
|
90
90
|
customLogger: createViteLogger(logger, settings.config.vite.logLevel),
|
|
91
91
|
appType: "custom",
|
|
92
92
|
optimizeDeps: {
|
|
93
|
-
// Scan
|
|
94
|
-
entries: [
|
|
95
|
-
`${srcDirPattern}!(pages)/**/*`,
|
|
96
|
-
// All files except for pages
|
|
97
|
-
`${srcDirPattern}pages/**/!(*.js|*.mjs|*.ts|*.mts)`,
|
|
98
|
-
// All pages except for endpoints
|
|
99
|
-
`${srcDirPattern}pages/**/_*.{js,mjs,ts,mts}`,
|
|
100
|
-
// Remaining JS/TS files prefixed with `_` (not endpoints)
|
|
101
|
-
`${srcDirPattern}pages/**/_*/**/*.{js,mjs,ts,mts}`
|
|
102
|
-
// Remaining JS/TS files within directories prefixed with `_` (not endpoints)
|
|
103
|
-
],
|
|
93
|
+
// Scan for component code within `srcDir`
|
|
94
|
+
entries: [`${srcDirPattern}**/*.{jsx,tsx,vue,svelte,html,astro}`],
|
|
104
95
|
exclude: ["astro", "node-fetch"]
|
|
105
96
|
},
|
|
106
97
|
plugins: [
|
|
@@ -28,7 +28,9 @@ async function createContainer({
|
|
|
28
28
|
base,
|
|
29
29
|
server: { host, headers, open: serverOpen }
|
|
30
30
|
} = settings.config;
|
|
31
|
-
const
|
|
31
|
+
const isServerOpenURL = typeof serverOpen == "string" && !isRestart;
|
|
32
|
+
const isServerOpenBoolean = serverOpen && !isRestart;
|
|
33
|
+
const open = isServerOpenURL ? serverOpen : isServerOpenBoolean ? base : false;
|
|
32
34
|
const rendererClientEntries = settings.renderers.map((r) => r.clientEntrypoint).filter(Boolean);
|
|
33
35
|
const viteConfig = await createVite(
|
|
34
36
|
{
|
package/dist/core/dev/dev.js
CHANGED
|
@@ -19,7 +19,7 @@ async function dev(inlineConfig) {
|
|
|
19
19
|
await telemetry.record([]);
|
|
20
20
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
21
21
|
const logger = restart.container.logger;
|
|
22
|
-
const currentVersion = "4.11.
|
|
22
|
+
const currentVersion = "4.11.6";
|
|
23
23
|
const isPrerelease = currentVersion.includes("-");
|
|
24
24
|
if (!isPrerelease) {
|
|
25
25
|
try {
|
|
@@ -1106,7 +1106,7 @@ export declare const RouteNotFound: {
|
|
|
1106
1106
|
export declare const EnvInvalidVariables: {
|
|
1107
1107
|
name: string;
|
|
1108
1108
|
title: string;
|
|
1109
|
-
message: (
|
|
1109
|
+
message: (errors: Array<string>) => string;
|
|
1110
1110
|
};
|
|
1111
1111
|
/**
|
|
1112
1112
|
* @docs
|
|
@@ -399,9 +399,9 @@ const RouteNotFound = {
|
|
|
399
399
|
const EnvInvalidVariables = {
|
|
400
400
|
name: "EnvInvalidVariables",
|
|
401
401
|
title: "Invalid Environment Variables",
|
|
402
|
-
message: (
|
|
402
|
+
message: (errors) => `The following environment variables defined in \`experimental.env.schema\` are invalid:
|
|
403
403
|
|
|
404
|
-
${
|
|
404
|
+
${errors.map((err) => `- ${err}`).join("\n")}
|
|
405
405
|
`
|
|
406
406
|
};
|
|
407
407
|
const EnvInvalidVariable = {
|
package/dist/core/messages.js
CHANGED
|
@@ -37,7 +37,7 @@ function serverStart({
|
|
|
37
37
|
host,
|
|
38
38
|
base
|
|
39
39
|
}) {
|
|
40
|
-
const version = "4.11.
|
|
40
|
+
const version = "4.11.6";
|
|
41
41
|
const localPrefix = `${dim("\u2503")} Local `;
|
|
42
42
|
const networkPrefix = `${dim("\u2503")} Network `;
|
|
43
43
|
const emptyPrefix = " ".repeat(11);
|
|
@@ -269,7 +269,7 @@ function printHelp({
|
|
|
269
269
|
message.push(
|
|
270
270
|
linebreak(),
|
|
271
271
|
` ${bgGreen(black(` ${commandName} `))} ${green(
|
|
272
|
-
`v${"4.11.
|
|
272
|
+
`v${"4.11.6"}`
|
|
273
273
|
)} ${headline}`
|
|
274
274
|
);
|
|
275
275
|
}
|
package/dist/env/schema.d.ts
CHANGED
|
@@ -220,7 +220,7 @@ declare const EnvFieldMetadata: z.ZodUnion<[z.ZodObject<{
|
|
|
220
220
|
context: "server";
|
|
221
221
|
access: "secret";
|
|
222
222
|
}>]>;
|
|
223
|
-
export declare const EnvSchema: z.ZodRecord<z.ZodString, z.ZodIntersection<z.ZodUnion<[z.ZodObject<{
|
|
223
|
+
export declare const EnvSchema: z.ZodRecord<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>, z.ZodIntersection<z.ZodUnion<[z.ZodObject<{
|
|
224
224
|
context: z.ZodLiteral<"client">;
|
|
225
225
|
access: z.ZodLiteral<"public">;
|
|
226
226
|
}, "strip", z.ZodTypeAny, {
|
package/dist/env/schema.js
CHANGED
|
@@ -69,13 +69,12 @@ const EnvFieldMetadata = z.union([
|
|
|
69
69
|
PublicServerEnvFieldMetadata,
|
|
70
70
|
SecretServerEnvFieldMetadata
|
|
71
71
|
]);
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
);
|
|
72
|
+
const EnvSchemaKey = z.string().min(1).refine(([firstChar]) => isNaN(Number.parseInt(firstChar)), {
|
|
73
|
+
message: "A valid variable name cannot start with a number."
|
|
74
|
+
}).refine((str) => /^[A-Z0-9_]+$/.test(str), {
|
|
75
|
+
message: "A valid variable name can only contain uppercase letters, numbers and underscores."
|
|
76
|
+
});
|
|
77
|
+
const EnvSchema = z.record(EnvSchemaKey, z.intersection(EnvFieldMetadata, EnvFieldType));
|
|
79
78
|
export {
|
|
80
79
|
EnvSchema
|
|
81
80
|
};
|
package/dist/env/validators.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { EnvFieldType } from './schema.js';
|
|
2
2
|
export type ValidationResultValue = EnvFieldType['default'];
|
|
3
|
+
export type ValidationResultErrors = ['missing'] | ['type'] | Array<string>;
|
|
3
4
|
type ValidationResult = {
|
|
4
5
|
ok: true;
|
|
5
|
-
type: string;
|
|
6
6
|
value: ValidationResultValue;
|
|
7
7
|
} | {
|
|
8
8
|
ok: false;
|
|
9
|
-
|
|
9
|
+
errors: ValidationResultErrors;
|
|
10
10
|
};
|
|
11
11
|
export declare function getEnvFieldType(options: EnvFieldType): string;
|
|
12
12
|
export declare function validateEnvVariable(value: string | undefined, options: EnvFieldType): ValidationResult;
|
package/dist/env/validators.js
CHANGED
|
@@ -9,72 +9,106 @@ function getEnvFieldType(options) {
|
|
|
9
9
|
return `${type}${optional ? " | undefined" : ""}`;
|
|
10
10
|
}
|
|
11
11
|
const stringValidator = ({ max, min, length, url, includes, startsWith, endsWith }) => (input) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
if (typeof input !== "string") {
|
|
13
|
+
return {
|
|
14
|
+
ok: false,
|
|
15
|
+
errors: ["type"]
|
|
16
|
+
};
|
|
15
17
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
const errors = [];
|
|
19
|
+
if (max !== void 0 && !(input.length <= max)) {
|
|
20
|
+
errors.push("max");
|
|
18
21
|
}
|
|
19
|
-
if (
|
|
20
|
-
|
|
22
|
+
if (min !== void 0 && !(input.length >= min)) {
|
|
23
|
+
errors.push("min");
|
|
21
24
|
}
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
25
|
+
if (length !== void 0 && !(input.length === length)) {
|
|
26
|
+
errors.push("length");
|
|
27
|
+
}
|
|
28
|
+
if (url !== void 0 && !URL.canParse(input)) {
|
|
29
|
+
errors.push("url");
|
|
28
30
|
}
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
+
if (includes !== void 0 && !input.includes(includes)) {
|
|
32
|
+
errors.push("includes");
|
|
31
33
|
}
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
+
if (startsWith !== void 0 && !input.startsWith(startsWith)) {
|
|
35
|
+
errors.push("startsWith");
|
|
34
36
|
}
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
+
if (endsWith !== void 0 && !input.endsWith(endsWith)) {
|
|
38
|
+
errors.push("endsWith");
|
|
39
|
+
}
|
|
40
|
+
if (errors.length > 0) {
|
|
41
|
+
return {
|
|
42
|
+
ok: false,
|
|
43
|
+
errors
|
|
44
|
+
};
|
|
37
45
|
}
|
|
38
46
|
return {
|
|
39
|
-
|
|
40
|
-
|
|
47
|
+
ok: true,
|
|
48
|
+
value: input
|
|
41
49
|
};
|
|
42
50
|
};
|
|
43
51
|
const numberValidator = ({ gt, min, lt, max, int }) => (input) => {
|
|
44
52
|
const num = parseFloat(input ?? "");
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
if (isNaN(num)) {
|
|
54
|
+
return {
|
|
55
|
+
ok: false,
|
|
56
|
+
errors: ["type"]
|
|
57
|
+
};
|
|
48
58
|
}
|
|
49
|
-
|
|
50
|
-
|
|
59
|
+
const errors = [];
|
|
60
|
+
if (gt !== void 0 && !(num > gt)) {
|
|
61
|
+
errors.push("gt");
|
|
51
62
|
}
|
|
52
|
-
if (
|
|
53
|
-
|
|
63
|
+
if (min !== void 0 && !(num >= min)) {
|
|
64
|
+
errors.push("min");
|
|
54
65
|
}
|
|
55
|
-
if (
|
|
56
|
-
|
|
66
|
+
if (lt !== void 0 && !(num < lt)) {
|
|
67
|
+
errors.push("lt");
|
|
57
68
|
}
|
|
58
|
-
if (
|
|
69
|
+
if (max !== void 0 && !(num <= max)) {
|
|
70
|
+
errors.push("max");
|
|
71
|
+
}
|
|
72
|
+
if (int !== void 0) {
|
|
59
73
|
const isInt = Number.isInteger(num);
|
|
60
|
-
|
|
74
|
+
if (!(int ? isInt : !isInt)) {
|
|
75
|
+
errors.push("int");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (errors.length > 0) {
|
|
79
|
+
return {
|
|
80
|
+
ok: false,
|
|
81
|
+
errors
|
|
82
|
+
};
|
|
61
83
|
}
|
|
62
84
|
return {
|
|
63
|
-
|
|
64
|
-
|
|
85
|
+
ok: true,
|
|
86
|
+
value: num
|
|
65
87
|
};
|
|
66
88
|
};
|
|
67
89
|
const booleanValidator = (input) => {
|
|
68
90
|
const bool = input === "true" ? true : input === "false" ? false : void 0;
|
|
91
|
+
if (typeof bool !== "boolean") {
|
|
92
|
+
return {
|
|
93
|
+
ok: false,
|
|
94
|
+
errors: ["type"]
|
|
95
|
+
};
|
|
96
|
+
}
|
|
69
97
|
return {
|
|
70
|
-
|
|
71
|
-
|
|
98
|
+
ok: true,
|
|
99
|
+
value: bool
|
|
72
100
|
};
|
|
73
101
|
};
|
|
74
102
|
const enumValidator = ({ values }) => (input) => {
|
|
103
|
+
if (!(typeof input === "string" ? values.includes(input) : false)) {
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
errors: ["type"]
|
|
107
|
+
};
|
|
108
|
+
}
|
|
75
109
|
return {
|
|
76
|
-
|
|
77
|
-
|
|
110
|
+
ok: true,
|
|
111
|
+
value: input
|
|
78
112
|
};
|
|
79
113
|
};
|
|
80
114
|
function selectValidator(options) {
|
|
@@ -90,29 +124,20 @@ function selectValidator(options) {
|
|
|
90
124
|
}
|
|
91
125
|
}
|
|
92
126
|
function validateEnvVariable(value, options) {
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
if (options.optional || options.default !== void 0) {
|
|
96
|
-
if (value === void 0) {
|
|
97
|
-
return {
|
|
98
|
-
ok: true,
|
|
99
|
-
value: options.default,
|
|
100
|
-
type
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
const { valid, parsed } = validator(value);
|
|
105
|
-
if (valid) {
|
|
127
|
+
const isOptional = options.optional || options.default !== void 0;
|
|
128
|
+
if (isOptional && value === void 0) {
|
|
106
129
|
return {
|
|
107
130
|
ok: true,
|
|
108
|
-
value:
|
|
109
|
-
type
|
|
131
|
+
value: options.default
|
|
110
132
|
};
|
|
111
133
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
134
|
+
if (!isOptional && value === void 0) {
|
|
135
|
+
return {
|
|
136
|
+
ok: false,
|
|
137
|
+
errors: ["missing"]
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return selectValidator(options)(value);
|
|
116
141
|
}
|
|
117
142
|
export {
|
|
118
143
|
getEnvFieldType,
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
VIRTUAL_MODULES_IDS,
|
|
7
7
|
VIRTUAL_MODULES_IDS_VALUES
|
|
8
8
|
} from "./constants.js";
|
|
9
|
-
import { validateEnvVariable } from "./validators.js";
|
|
9
|
+
import { getEnvFieldType, validateEnvVariable } from "./validators.js";
|
|
10
10
|
function astroEnv({
|
|
11
11
|
settings,
|
|
12
12
|
mode,
|
|
@@ -32,7 +32,11 @@ function astroEnv({
|
|
|
32
32
|
process.env[key] = value;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
const validatedVariables = validatePublicVariables({
|
|
35
|
+
const validatedVariables = validatePublicVariables({
|
|
36
|
+
schema,
|
|
37
|
+
loadedEnv,
|
|
38
|
+
validateSecrets: settings.config.experimental.env?.validateSecrets ?? false
|
|
39
|
+
});
|
|
36
40
|
templates = {
|
|
37
41
|
...getTemplates(schema, fs, validatedVariables),
|
|
38
42
|
internal: `export const schema = ${JSON.stringify(schema)};`
|
|
@@ -70,28 +74,38 @@ function resolveVirtualModuleId(id) {
|
|
|
70
74
|
}
|
|
71
75
|
function validatePublicVariables({
|
|
72
76
|
schema,
|
|
73
|
-
loadedEnv
|
|
77
|
+
loadedEnv,
|
|
78
|
+
validateSecrets
|
|
74
79
|
}) {
|
|
75
80
|
const valid = [];
|
|
76
81
|
const invalid = [];
|
|
77
82
|
for (const [key, options] of Object.entries(schema)) {
|
|
78
|
-
|
|
83
|
+
const variable = loadedEnv[key] === "" ? void 0 : loadedEnv[key];
|
|
84
|
+
if (options.access === "secret" && !validateSecrets) {
|
|
79
85
|
continue;
|
|
80
86
|
}
|
|
81
|
-
const
|
|
82
|
-
const
|
|
83
|
-
if (result.ok) {
|
|
84
|
-
|
|
85
|
-
} else {
|
|
86
|
-
|
|
87
|
+
const result = validateEnvVariable(variable, options);
|
|
88
|
+
const type = getEnvFieldType(options);
|
|
89
|
+
if (!result.ok) {
|
|
90
|
+
invalid.push({ key, type, errors: result.errors });
|
|
91
|
+
} else if (options.access === "public") {
|
|
92
|
+
valid.push({ key, value: result.value, type, context: options.context });
|
|
87
93
|
}
|
|
88
94
|
}
|
|
89
95
|
if (invalid.length > 0) {
|
|
96
|
+
const _errors = [];
|
|
97
|
+
for (const { key, type, errors } of invalid) {
|
|
98
|
+
if (errors[0] === "missing") {
|
|
99
|
+
_errors.push(`${key} is missing`);
|
|
100
|
+
} else if (errors[0] === "type") {
|
|
101
|
+
_errors.push(`${key}'s type is invalid, expected: ${type}`);
|
|
102
|
+
} else {
|
|
103
|
+
_errors.push(`The following constraints for ${key} are not met: ${errors.join(", ")}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
90
106
|
throw new AstroError({
|
|
91
107
|
...AstroErrorData.EnvInvalidVariables,
|
|
92
|
-
message: AstroErrorData.EnvInvalidVariables.message(
|
|
93
|
-
invalid.map(({ key, type }) => `Variable ${key} is not of type: ${type}.`).join("\n")
|
|
94
|
-
)
|
|
108
|
+
message: AstroErrorData.EnvInvalidVariables.message(_errors)
|
|
95
109
|
});
|
|
96
110
|
}
|
|
97
111
|
return valid;
|
|
@@ -91,6 +91,7 @@ const aria_non_interactive_roles = [
|
|
|
91
91
|
"rowheader",
|
|
92
92
|
"search",
|
|
93
93
|
"status",
|
|
94
|
+
"tabpanel",
|
|
94
95
|
"term",
|
|
95
96
|
"timer",
|
|
96
97
|
"toolbar",
|
|
@@ -422,7 +423,7 @@ const a11y = [
|
|
|
422
423
|
title: "Invalid `tabindex` on non-interactive element",
|
|
423
424
|
description: 'The `tabindex` attribute should only be used on interactive elements, as it can be confusing for keyboard-only users to navigate through non-interactive elements. If your element is only conditionally interactive, consider using `tabindex="-1"` to make it focusable only when it is actually interactive.',
|
|
424
425
|
message: (element) => `${element.localName} elements should not have \`tabindex\` attribute`,
|
|
425
|
-
selector:
|
|
426
|
+
selector: '[tabindex]:not([role="tabpanel"])',
|
|
426
427
|
match(element) {
|
|
427
428
|
const isScrollable = element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
|
|
428
429
|
if (isScrollable) return false;
|
|
@@ -2,6 +2,8 @@ import { clsx } from "clsx";
|
|
|
2
2
|
import { HTMLString, markHTMLString } from "../escape.js";
|
|
3
3
|
const voidElementNames = /^(area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/i;
|
|
4
4
|
const htmlBooleanAttributes = /^(?:allowfullscreen|async|autofocus|autoplay|controls|default|defer|disabled|disablepictureinpicture|disableremoteplayback|formnovalidate|hidden|loop|nomodule|novalidate|open|playsinline|readonly|required|reversed|scoped|seamless|itemscope)$/i;
|
|
5
|
+
const htmlEnumAttributes = /^(?:contenteditable|draggable|spellcheck|value)$/i;
|
|
6
|
+
const svgEnumAttributes = /^(?:autoReverse|externalResourcesRequired|focusable|preserveAlpha)$/i;
|
|
5
7
|
const AMPERSAND_REGEX = /&/g;
|
|
6
8
|
const DOUBLE_QUOTE_REGEX = /"/g;
|
|
7
9
|
const STATIC_DIRECTIVES = /* @__PURE__ */ new Set(["set:html", "set:text"]);
|
|
@@ -36,6 +38,12 @@ function addAttribute(value, key, shouldEscape = true) {
|
|
|
36
38
|
if (value == null) {
|
|
37
39
|
return "";
|
|
38
40
|
}
|
|
41
|
+
if (value === false) {
|
|
42
|
+
if (htmlEnumAttributes.test(key) || svgEnumAttributes.test(key)) {
|
|
43
|
+
return markHTMLString(` ${key}="false"`);
|
|
44
|
+
}
|
|
45
|
+
return "";
|
|
46
|
+
}
|
|
39
47
|
if (STATIC_DIRECTIVES.has(key)) {
|
|
40
48
|
console.warn(`[astro] The "${key}" directive cannot be applied dynamically at runtime. It will not be rendered as an attribute.
|
|
41
49
|
|
|
@@ -65,13 +73,11 @@ Make sure to use the static attribute syntax (\`${key}={value}\`) instead of the
|
|
|
65
73
|
if (typeof value === "string" && value.includes("&") && isHttpUrl(value)) {
|
|
66
74
|
return markHTMLString(` ${key}="${toAttributeString(value, false)}"`);
|
|
67
75
|
}
|
|
68
|
-
if (htmlBooleanAttributes.test(key)) {
|
|
69
|
-
return markHTMLString(value ? ` ${key}` : "");
|
|
70
|
-
}
|
|
71
|
-
if (value === "") {
|
|
76
|
+
if (value === true && (key.startsWith("data-") || htmlBooleanAttributes.test(key))) {
|
|
72
77
|
return markHTMLString(` ${key}`);
|
|
78
|
+
} else {
|
|
79
|
+
return markHTMLString(` ${key}="${toAttributeString(value, shouldEscape)}"`);
|
|
73
80
|
}
|
|
74
|
-
return markHTMLString(` ${key}="${toAttributeString(value, shouldEscape)}"`);
|
|
75
81
|
}
|
|
76
82
|
function internalSpreadAttributes(values, shouldEscape = true) {
|
|
77
83
|
let output = "";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro",
|
|
3
|
-
"version": "4.11.
|
|
3
|
+
"version": "4.11.6",
|
|
4
4
|
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "withastro",
|
|
@@ -109,19 +109,19 @@
|
|
|
109
109
|
"vendor"
|
|
110
110
|
],
|
|
111
111
|
"dependencies": {
|
|
112
|
-
"@astrojs/compiler": "^2.8.
|
|
113
|
-
"@babel/core": "^7.24.
|
|
114
|
-
"@babel/generator": "^7.24.
|
|
115
|
-
"@babel/parser": "^7.24.
|
|
112
|
+
"@astrojs/compiler": "^2.8.2",
|
|
113
|
+
"@babel/core": "^7.24.9",
|
|
114
|
+
"@babel/generator": "^7.24.10",
|
|
115
|
+
"@babel/parser": "^7.24.8",
|
|
116
116
|
"@babel/plugin-transform-react-jsx": "^7.24.7",
|
|
117
|
-
"@babel/traverse": "^7.24.
|
|
118
|
-
"@babel/types": "^7.24.
|
|
117
|
+
"@babel/traverse": "^7.24.8",
|
|
118
|
+
"@babel/types": "^7.24.9",
|
|
119
119
|
"@types/babel__core": "^7.20.5",
|
|
120
120
|
"@types/cookie": "^0.6.0",
|
|
121
|
-
"acorn": "^8.12.
|
|
121
|
+
"acorn": "^8.12.1",
|
|
122
122
|
"aria-query": "^5.3.0",
|
|
123
|
-
"axobject-query": "^4.
|
|
124
|
-
"boxen": "^
|
|
123
|
+
"axobject-query": "^4.1.0",
|
|
124
|
+
"boxen": "^8.0.0",
|
|
125
125
|
"chokidar": "^3.6.0",
|
|
126
126
|
"ci-info": "^4.0.0",
|
|
127
127
|
"clsx": "^2.1.1",
|
|
@@ -149,22 +149,22 @@
|
|
|
149
149
|
"magic-string": "^0.30.10",
|
|
150
150
|
"mrmime": "^2.0.0",
|
|
151
151
|
"ora": "^8.0.1",
|
|
152
|
-
"p-limit": "^
|
|
152
|
+
"p-limit": "^6.1.0",
|
|
153
153
|
"p-queue": "^8.0.1",
|
|
154
154
|
"path-to-regexp": "^6.2.2",
|
|
155
|
-
"preferred-pm": "^
|
|
155
|
+
"preferred-pm": "^4.0.0",
|
|
156
156
|
"prompts": "^2.4.2",
|
|
157
157
|
"rehype": "^13.0.1",
|
|
158
158
|
"semver": "^7.6.2",
|
|
159
|
-
"shiki": "^1.10.
|
|
159
|
+
"shiki": "^1.10.3",
|
|
160
160
|
"string-width": "^7.2.0",
|
|
161
161
|
"strip-ansi": "^7.1.0",
|
|
162
162
|
"tsconfck": "^3.1.1",
|
|
163
163
|
"unist-util-visit": "^5.0.0",
|
|
164
|
-
"vfile": "^6.0.
|
|
165
|
-
"vite": "^5.3.
|
|
164
|
+
"vfile": "^6.0.2",
|
|
165
|
+
"vite": "^5.3.4",
|
|
166
166
|
"vitefu": "^0.2.5",
|
|
167
|
-
"which-pm": "^
|
|
167
|
+
"which-pm": "^3.0.0",
|
|
168
168
|
"yargs-parser": "^21.1.1",
|
|
169
169
|
"zod": "^3.23.8",
|
|
170
170
|
"zod-to-json-schema": "^3.23.1",
|
|
@@ -176,8 +176,8 @@
|
|
|
176
176
|
"sharp": "^0.33.3"
|
|
177
177
|
},
|
|
178
178
|
"devDependencies": {
|
|
179
|
-
"@astrojs/check": "^0.
|
|
180
|
-
"@playwright/test": "^1.45.
|
|
179
|
+
"@astrojs/check": "^0.8.1",
|
|
180
|
+
"@playwright/test": "^1.45.2",
|
|
181
181
|
"@types/aria-query": "^5.0.4",
|
|
182
182
|
"@types/babel__generator": "^7.6.8",
|
|
183
183
|
"@types/babel__traverse": "^7.20.6",
|
|
@@ -200,6 +200,7 @@
|
|
|
200
200
|
"@types/yargs-parser": "^21.0.3",
|
|
201
201
|
"cheerio": "1.0.0-rc.12",
|
|
202
202
|
"eol": "^0.9.1",
|
|
203
|
+
"expect-type": "^0.19.0",
|
|
203
204
|
"mdast-util-mdx": "^3.0.0",
|
|
204
205
|
"mdast-util-mdx-jsx": "^3.1.2",
|
|
205
206
|
"memfs": "^4.9.3",
|
|
@@ -209,8 +210,8 @@
|
|
|
209
210
|
"rehype-slug": "^6.0.0",
|
|
210
211
|
"rehype-toc": "^3.0.2",
|
|
211
212
|
"remark-code-titles": "^0.1.2",
|
|
212
|
-
"rollup": "^4.18.
|
|
213
|
-
"sass": "^1.77.
|
|
213
|
+
"rollup": "^4.18.1",
|
|
214
|
+
"sass": "^1.77.8",
|
|
214
215
|
"srcset-parse": "^1.1.0",
|
|
215
216
|
"undici": "^6.19.2",
|
|
216
217
|
"unified": "^11.0.5",
|
|
@@ -230,12 +231,13 @@
|
|
|
230
231
|
"build:ci": "pnpm run prebuild && astro-scripts build \"src/**/*.{ts,js}\" && pnpm run postbuild",
|
|
231
232
|
"dev": "astro-scripts dev --copy-wasm --prebuild \"src/runtime/server/astro-island.ts\" --prebuild \"src/runtime/client/{idle,load,media,only,visible}.ts\" \"src/**/*.{ts,js}\"",
|
|
232
233
|
"postbuild": "astro-scripts copy \"src/**/*.astro\" && astro-scripts copy \"src/**/*.wasm\"",
|
|
233
|
-
"test": "pnpm run test:node",
|
|
234
|
+
"test": "pnpm run test:node && pnpm run test:types",
|
|
234
235
|
"test:match": "pnpm run test:node --match",
|
|
235
236
|
"test:e2e": "pnpm test:e2e:chrome && pnpm test:e2e:firefox",
|
|
236
237
|
"test:e2e:match": "playwright test -g",
|
|
237
238
|
"test:e2e:chrome": "playwright test",
|
|
238
239
|
"test:e2e:firefox": "playwright test --config playwright.firefox.config.js",
|
|
240
|
+
"test:types": "tsc --project tsconfig.tests.json",
|
|
239
241
|
"test:node": "astro-scripts test \"test/**/*.test.js\""
|
|
240
242
|
}
|
|
241
243
|
}
|