astro 5.0.3 → 5.0.5

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.
Files changed (41) hide show
  1. package/dist/assets/utils/node/emitAsset.d.ts +1 -1
  2. package/dist/assets/utils/node/emitAsset.js +2 -2
  3. package/dist/assets/vite-plugin-assets.js +6 -1
  4. package/dist/cli/info/index.js +2 -2
  5. package/dist/container/index.js +0 -1
  6. package/dist/content/content-layer.js +5 -4
  7. package/dist/content/mutable-data-store.js +2 -2
  8. package/dist/content/runtime-assets.d.ts +1 -1
  9. package/dist/content/runtime-assets.js +2 -1
  10. package/dist/content/utils.d.ts +2 -2
  11. package/dist/content/utils.js +9 -3
  12. package/dist/content/vite-plugin-content-assets.js +1 -1
  13. package/dist/content/vite-plugin-content-imports.js +2 -0
  14. package/dist/core/app/index.js +0 -1
  15. package/dist/core/app/types.d.ts +0 -1
  16. package/dist/core/base-pipeline.js +0 -3
  17. package/dist/core/build/generate.js +1 -2
  18. package/dist/core/build/pipeline.js +4 -5
  19. package/dist/core/build/plugins/plugin-manifest.js +1 -2
  20. package/dist/core/constants.js +1 -1
  21. package/dist/core/create-vite.js +4 -2
  22. package/dist/core/dev/dev.js +1 -1
  23. package/dist/core/errors/errors-data.d.ts +1 -1
  24. package/dist/core/messages.js +2 -2
  25. package/dist/core/middleware/index.d.ts +5 -1
  26. package/dist/core/middleware/index.js +6 -6
  27. package/dist/core/request.d.ts +1 -1
  28. package/dist/core/request.js +0 -3
  29. package/dist/core/util.js +3 -2
  30. package/dist/env/env-loader.d.ts +6 -0
  31. package/dist/env/env-loader.js +45 -0
  32. package/dist/env/runtime.d.ts +2 -2
  33. package/dist/env/runtime.js +2 -2
  34. package/dist/env/vite-plugin-env.d.ts +4 -2
  35. package/dist/env/vite-plugin-env.js +19 -10
  36. package/dist/vite-plugin-astro-server/plugin.js +0 -1
  37. package/dist/vite-plugin-astro-server/route.js +1 -1
  38. package/dist/vite-plugin-env/index.d.ts +3 -3
  39. package/dist/vite-plugin-env/index.js +2 -36
  40. package/package.json +2 -2
  41. package/templates/env.mjs +11 -5
@@ -6,5 +6,5 @@ type ImageMetadataWithContents = ImageMetadata & {
6
6
  };
7
7
  export declare function emitESMImage(id: string | undefined,
8
8
  /** @deprecated */
9
- _watchMode: boolean, fileEmitter?: FileEmitter): Promise<ImageMetadataWithContents | undefined>;
9
+ _watchMode: boolean, experimentalSvgEnabled: boolean, fileEmitter?: FileEmitter): Promise<ImageMetadataWithContents | undefined>;
10
10
  export {};
@@ -3,7 +3,7 @@ import path from "node:path";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
4
  import { prependForwardSlash, slash } from "../../../core/path.js";
5
5
  import { imageMetadata } from "../metadata.js";
6
- async function emitESMImage(id, _watchMode, fileEmitter) {
6
+ async function emitESMImage(id, _watchMode, experimentalSvgEnabled, fileEmitter) {
7
7
  if (!id) {
8
8
  return void 0;
9
9
  }
@@ -24,7 +24,7 @@ async function emitESMImage(id, _watchMode, fileEmitter) {
24
24
  writable: false,
25
25
  value: id
26
26
  });
27
- if (fileMetadata.format === "svg") {
27
+ if (fileMetadata.format === "svg" && experimentalSvgEnabled === true) {
28
28
  emittedImage.contents = fileData;
29
29
  }
30
30
  let isBuild = typeof fileEmitter === "function";
@@ -167,7 +167,12 @@ function assets({ settings }) {
167
167
  return;
168
168
  }
169
169
  const emitFile = shouldEmitFile ? this.emitFile : void 0;
170
- const imageMetadata = await emitESMImage(id, this.meta.watchMode, emitFile);
170
+ const imageMetadata = await emitESMImage(
171
+ id,
172
+ this.meta.watchMode,
173
+ !!settings.config.experimental.svg,
174
+ emitFile
175
+ );
171
176
  if (!imageMetadata) {
172
177
  throw new AstroError({
173
178
  ...AstroErrorData.ImageNotFound,
@@ -46,7 +46,7 @@ async function copyToClipboard(text, force) {
46
46
  command = "clip";
47
47
  } else {
48
48
  const unixCommands = [
49
- ["xclip", ["-sel", "clipboard", "-l", "1"]],
49
+ ["xclip", ["-selection", "clipboard", "-l", "1"]],
50
50
  ["wl-copy", []]
51
51
  ];
52
52
  for (const [unixCommand, unixArgs] of unixCommands) {
@@ -77,7 +77,7 @@ async function copyToClipboard(text, force) {
77
77
  if (!shouldCopy) return;
78
78
  }
79
79
  try {
80
- const result = spawnSync(command, args, { input: text });
80
+ const result = spawnSync(command, args, { input: text, stdio: ["pipe", "ignore", "ignore"] });
81
81
  if (result.error) {
82
82
  throw result.error;
83
83
  }
@@ -36,7 +36,6 @@ function createManifest(manifest, renderers, middleware) {
36
36
  i18n: manifest?.i18n,
37
37
  checkOrigin: false,
38
38
  middleware: manifest?.middleware ?? middlewareInstance,
39
- envGetSecretEnabled: false,
40
39
  key: createKey()
41
40
  };
42
41
  }
@@ -114,7 +114,7 @@ class ContentLayer {
114
114
  logger.info("Content config changed");
115
115
  shouldClear = true;
116
116
  }
117
- if (previousAstroVersion !== "5.0.3") {
117
+ if (previousAstroVersion !== "5.0.5") {
118
118
  logger.info("Astro version changed");
119
119
  shouldClear = true;
120
120
  }
@@ -122,8 +122,8 @@ class ContentLayer {
122
122
  logger.info("Clearing content store");
123
123
  this.#store.clearAll();
124
124
  }
125
- if ("5.0.3") {
126
- await this.#store.metaStore().set("astro-version", "5.0.3");
125
+ if ("5.0.5") {
126
+ await this.#store.metaStore().set("astro-version", "5.0.5");
127
127
  }
128
128
  if (currentConfigDigest) {
129
129
  await this.#store.metaStore().set("config-digest", currentConfigDigest);
@@ -156,7 +156,8 @@ class ContentLayer {
156
156
  }
157
157
  },
158
158
  collectionWithResolvedSchema,
159
- false
159
+ false,
160
+ !!this.#settings.config.experimental.svg
160
161
  );
161
162
  return parsedData;
162
163
  };
@@ -73,7 +73,7 @@ class MutableDataStore extends ImmutableDataStore {
73
73
  const exports = [];
74
74
  this.#assetImports.forEach((id) => {
75
75
  const symbol = importIdToSymbolName(id);
76
- imports.push(`import ${symbol} from '${id}';`);
76
+ imports.push(`import ${symbol} from ${JSON.stringify(id)};`);
77
77
  exports.push(`[${JSON.stringify(id)}, ${symbol}]`);
78
78
  });
79
79
  const code = (
@@ -104,7 +104,7 @@ export default new Map([${exports.join(", ")}]);
104
104
  }
105
105
  const lines = [];
106
106
  for (const [fileName, specifier] of this.#moduleImports) {
107
- lines.push(`['${fileName}', () => import('${specifier}')]`);
107
+ lines.push(`[${JSON.stringify(fileName)}, () => import(${JSON.stringify(specifier)})]`);
108
108
  }
109
109
  const code = `
110
110
  export default new Map([
@@ -1,6 +1,6 @@
1
1
  import type { PluginContext } from 'rollup';
2
2
  import { z } from 'zod';
3
- export declare function createImage(pluginContext: PluginContext, shouldEmitFile: boolean, entryFilePath: string): () => z.ZodEffects<z.ZodString, z.ZodNever | {
3
+ export declare function createImage(pluginContext: PluginContext, shouldEmitFile: boolean, entryFilePath: string, experimentalSvgEnabled: boolean): () => z.ZodEffects<z.ZodString, z.ZodNever | {
4
4
  ASTRO_ASSET: string;
5
5
  width: number;
6
6
  height: number;
@@ -1,12 +1,13 @@
1
1
  import { z } from "zod";
2
2
  import { emitESMImage } from "../assets/utils/node/emitAsset.js";
3
- function createImage(pluginContext, shouldEmitFile, entryFilePath) {
3
+ function createImage(pluginContext, shouldEmitFile, entryFilePath, experimentalSvgEnabled) {
4
4
  return () => {
5
5
  return z.string().transform(async (imagePath, ctx) => {
6
6
  const resolvedFilePath = (await pluginContext.resolve(imagePath, entryFilePath))?.id;
7
7
  const metadata = await emitESMImage(
8
8
  resolvedFilePath,
9
9
  pluginContext.meta.watchMode,
10
+ experimentalSvgEnabled,
10
11
  shouldEmitFile ? pluginContext.emitFile : void 0
11
12
  );
12
13
  if (!metadata) {
@@ -469,7 +469,7 @@ export declare function getEntryDataAndImages<TInputData extends Record<string,
469
469
  collection: string;
470
470
  unvalidatedData: TInputData;
471
471
  _internal: EntryInternal;
472
- }, collectionConfig: CollectionConfig, shouldEmitFile: boolean, pluginContext?: PluginContext): Promise<{
472
+ }, collectionConfig: CollectionConfig, shouldEmitFile: boolean, experimentalSvgEnabled: boolean, pluginContext?: PluginContext): Promise<{
473
473
  data: TOutputData;
474
474
  imageImports: Array<string>;
475
475
  }>;
@@ -478,7 +478,7 @@ export declare function getEntryData(entry: {
478
478
  collection: string;
479
479
  unvalidatedData: Record<string, unknown>;
480
480
  _internal: EntryInternal;
481
- }, collectionConfig: CollectionConfig, shouldEmitFile: boolean, pluginContext?: PluginContext): Promise<Record<string, unknown>>;
481
+ }, collectionConfig: CollectionConfig, shouldEmitFile: boolean, experimentalSvgEnabled: boolean, pluginContext?: PluginContext): Promise<Record<string, unknown>>;
482
482
  export declare function getContentEntryExts(settings: Pick<AstroSettings, 'contentEntryTypes'>): string[];
483
483
  export declare function getDataEntryExts(settings: Pick<AstroSettings, 'dataEntryTypes'>): string[];
484
484
  export declare function getEntryConfigByExtMap<TEntryType extends ContentEntryType | DataEntryType>(entryTypes: TEntryType[]): Map<string, TEntryType>;
@@ -110,7 +110,7 @@ function parseEntrySlug({
110
110
  });
111
111
  }
112
112
  }
113
- async function getEntryDataAndImages(entry, collectionConfig, shouldEmitFile, pluginContext) {
113
+ async function getEntryDataAndImages(entry, collectionConfig, shouldEmitFile, experimentalSvgEnabled, pluginContext) {
114
114
  let data;
115
115
  if (collectionConfig.type === "content" || collectionConfig._legacy) {
116
116
  const { slug, ...unvalidatedData } = entry.unvalidatedData;
@@ -123,7 +123,12 @@ async function getEntryDataAndImages(entry, collectionConfig, shouldEmitFile, pl
123
123
  if (typeof schema === "function") {
124
124
  if (pluginContext) {
125
125
  schema = schema({
126
- image: createImage(pluginContext, shouldEmitFile, entry._internal.filePath)
126
+ image: createImage(
127
+ pluginContext,
128
+ shouldEmitFile,
129
+ entry._internal.filePath,
130
+ experimentalSvgEnabled
131
+ )
127
132
  });
128
133
  } else if (collectionConfig.type === CONTENT_LAYER_TYPE) {
129
134
  schema = schema({
@@ -173,11 +178,12 @@ async function getEntryDataAndImages(entry, collectionConfig, shouldEmitFile, pl
173
178
  }
174
179
  return { data, imageImports: Array.from(imageImports) };
175
180
  }
176
- async function getEntryData(entry, collectionConfig, shouldEmitFile, pluginContext) {
181
+ async function getEntryData(entry, collectionConfig, shouldEmitFile, experimentalSvgEnabled, pluginContext) {
177
182
  const { data } = await getEntryDataAndImages(
178
183
  entry,
179
184
  collectionConfig,
180
185
  shouldEmitFile,
186
+ experimentalSvgEnabled,
181
187
  pluginContext
182
188
  );
183
189
  return data;
@@ -26,7 +26,7 @@ function astroContentAssetPropagationPlugin({
26
26
  const params = new URLSearchParams(query);
27
27
  const importerParam = params.get("importer");
28
28
  const importerPath = importerParam ? fileURLToPath(new URL(importerParam, settings.config.root)) : importer;
29
- const resolved = this.resolve(base, importerPath, { skipSelf: true, ...opts });
29
+ const resolved = await this.resolve(base, importerPath, { skipSelf: true, ...opts });
30
30
  if (!resolved) {
31
31
  throw new AstroError({
32
32
  ...AstroErrorData.ImageNotFound,
@@ -171,6 +171,7 @@ async function getContentEntryModule(params) {
171
171
  { id, collection, _internal, unvalidatedData },
172
172
  collectionConfig,
173
173
  params.shouldEmitFile,
174
+ !!params.config.experimental.svg,
174
175
  pluginContext
175
176
  ) : unvalidatedData;
176
177
  const contentEntryModule = {
@@ -196,6 +197,7 @@ async function getDataEntryModule(params) {
196
197
  { id, collection, _internal, unvalidatedData },
197
198
  collectionConfig,
198
199
  params.shouldEmitFile,
200
+ !!params.config.experimental.svg,
199
201
  pluginContext
200
202
  ) : unvalidatedData;
201
203
  const dataEntryModule = {
@@ -173,7 +173,6 @@ class App {
173
173
  this.#logger.error(null, error.stack);
174
174
  return this.#renderError(request, { status: 500, error, clientAddress });
175
175
  }
176
- Reflect.set(request, clientLocalsSymbol, locals);
177
176
  }
178
177
  if (!routeData) {
179
178
  routeData = this.match(request);
@@ -59,7 +59,6 @@ export type SSRManifest = {
59
59
  i18n: SSRManifestI18n | undefined;
60
60
  middleware?: () => Promise<AstroMiddlewareInstance> | AstroMiddlewareInstance;
61
61
  checkOrigin: boolean;
62
- envGetSecretEnabled: boolean;
63
62
  };
64
63
  export type SSRManifestI18n = {
65
64
  fallback: Record<string, string> | undefined;
@@ -1,8 +1,5 @@
1
- import { setGetEnv } from "../env/runtime.js";
2
1
  import { createI18nMiddleware } from "../i18n/middleware.js";
3
2
  import { createOriginCheckMiddleware } from "./app/middlewares.js";
4
- import { AstroError } from "./errors/errors.js";
5
- import { AstroErrorData } from "./errors/index.js";
6
3
  import { NOOP_MIDDLEWARE_FN } from "./middleware/noop-middleware.js";
7
4
  import { sequence } from "./middleware/sequence.js";
8
5
  import { RouteCache } from "./render/route-cache.js";
@@ -389,8 +389,7 @@ function createBuildManifest(settings, internals, renderers, middleware, key) {
389
389
  };
390
390
  },
391
391
  checkOrigin: (settings.config.security?.checkOrigin && settings.buildOutput === "server") ?? false,
392
- key,
393
- envGetSecretEnabled: false
392
+ key
394
393
  };
395
394
  }
396
395
  export {
@@ -94,11 +94,10 @@ class BuildPipeline extends Pipeline {
94
94
  }
95
95
  const renderersEntryUrl = new URL(`renderers.mjs?time=${Date.now()}`, baseDirectory);
96
96
  const renderers = await import(renderersEntryUrl.toString());
97
- const middleware = internals.middlewareEntryPoint ? await import(internals.middlewareEntryPoint.toString()).then((mod) => {
98
- return function() {
99
- return { onRequest: mod.onRequest };
100
- };
101
- }) : manifest.middleware;
97
+ const middleware = internals.middlewareEntryPoint ? async function() {
98
+ const mod = await import(internals.middlewareEntryPoint.toString());
99
+ return { onRequest: mod.onRequest };
100
+ } : manifest.middleware;
102
101
  if (!renderers) {
103
102
  throw new Error(
104
103
  "Astro couldn't find the emitted renderers. This is an internal error, please file an issue."
@@ -208,8 +208,7 @@ function buildManifest(opts, internals, staticFiles, encodedKey) {
208
208
  buildFormat: settings.config.build.format,
209
209
  checkOrigin: (settings.config.security?.checkOrigin && settings.buildOutput === "server") ?? false,
210
210
  serverIslandNameMap: Array.from(settings.serverIslandNameMap),
211
- key: encodedKey,
212
- envGetSecretEnabled: (unwrapSupportKind(settings.adapter?.supportedAstroFeatures.envGetSecret) ?? "unsupported") !== "unsupported"
211
+ key: encodedKey
213
212
  };
214
213
  }
215
214
  export {
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "5.0.3";
1
+ const ASTRO_VERSION = "5.0.5";
2
2
  const REROUTE_DIRECTIVE_HEADER = "X-Astro-Reroute";
3
3
  const REWRITE_DIRECTIVE_HEADER_KEY = "X-Astro-Rewrite";
4
4
  const REWRITE_DIRECTIVE_HEADER_VALUE = "yes";
@@ -12,6 +12,7 @@ import {
12
12
  astroContentImportPlugin,
13
13
  astroContentVirtualModPlugin
14
14
  } from "../content/index.js";
15
+ import { createEnvLoader } from "../env/env-loader.js";
15
16
  import { astroEnv } from "../env/vite-plugin-env.js";
16
17
  import astroInternationalization from "../i18n/vite-plugin-i18n.js";
17
18
  import astroPrefetch from "../prefetch/vite-plugin-prefetch.js";
@@ -83,6 +84,7 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
83
84
  }
84
85
  });
85
86
  const srcDirPattern = glob.convertPathToPattern(fileURLToPath(settings.config.srcDir));
87
+ const envLoader = createEnvLoader();
86
88
  const commonConfig = {
87
89
  // Tell Vite not to combine config from vite.config.js with our provided inline config
88
90
  configFile: false,
@@ -107,8 +109,8 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
107
109
  // the build to run very slow as the filewatcher is triggered often.
108
110
  command === "dev" && vitePluginAstroServer({ settings, logger, fs, manifest, ssrManifest }),
109
111
  // ssrManifest is only required in dev mode, where it gets created before a Vite instance is created, and get passed to this function
110
- envVitePlugin({ settings }),
111
- astroEnv({ settings, mode, sync }),
112
+ envVitePlugin({ envLoader }),
113
+ astroEnv({ settings, mode, sync, envLoader }),
112
114
  markdownVitePlugin({ settings, logger }),
113
115
  htmlVitePlugin(),
114
116
  astroPostprocessVitePlugin(),
@@ -22,7 +22,7 @@ async function dev(inlineConfig) {
22
22
  await telemetry.record([]);
23
23
  const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
24
24
  const logger = restart.container.logger;
25
- const currentVersion = "5.0.3";
25
+ const currentVersion = "5.0.5";
26
26
  const isPrerelease = currentVersion.includes("-");
27
27
  if (!isPrerelease) {
28
28
  try {
@@ -856,7 +856,7 @@ export declare const AstroGlobNoMatch: {
856
856
  /**
857
857
  * @docs
858
858
  * @see
859
- * - [Astro.redirect](https://docs.astro.build/en/reference/api-reference/#astroredirect)
859
+ * - [Astro.redirect](https://docs.astro.build/en/reference/api-reference/#redirect)
860
860
  * @description
861
861
  * A redirect must be given a location with the `Location` header.
862
862
  */
@@ -38,7 +38,7 @@ function serverStart({
38
38
  host,
39
39
  base
40
40
  }) {
41
- const version = "5.0.3";
41
+ const version = "5.0.5";
42
42
  const localPrefix = `${dim("\u2503")} Local `;
43
43
  const networkPrefix = `${dim("\u2503")} Network `;
44
44
  const emptyPrefix = " ".repeat(11);
@@ -276,7 +276,7 @@ function printHelp({
276
276
  message.push(
277
277
  linebreak(),
278
278
  ` ${bgGreen(black(` ${commandName} `))} ${green(
279
- `v${"5.0.3"}`
279
+ `v${"5.0.5"}`
280
280
  )} ${headline}`
281
281
  );
282
282
  }
@@ -22,11 +22,15 @@ export type CreateContext = {
22
22
  * User defined default locale
23
23
  */
24
24
  defaultLocale: string;
25
+ /**
26
+ * Initial value of the locals
27
+ */
28
+ locals: App.Locals;
25
29
  };
26
30
  /**
27
31
  * Creates a context to be passed to Astro middleware `onRequest` function.
28
32
  */
29
- declare function createContext({ request, params, userDefinedLocales, defaultLocale, }: CreateContext): APIContext;
33
+ declare function createContext({ request, params, userDefinedLocales, defaultLocale, locals, }: CreateContext): APIContext;
30
34
  /**
31
35
  * It attempts to serialize `value` and return it as a string.
32
36
  *
@@ -17,7 +17,8 @@ function createContext({
17
17
  request,
18
18
  params = {},
19
19
  userDefinedLocales = [],
20
- defaultLocale = ""
20
+ defaultLocale = "",
21
+ locals
21
22
  }) {
22
23
  let preferredLocale = void 0;
23
24
  let preferredLocaleList = void 0;
@@ -70,15 +71,14 @@ function createContext({
70
71
  return clientIpAddress;
71
72
  },
72
73
  get locals() {
73
- let locals = Reflect.get(request, clientLocalsSymbol);
74
+ let _locals = locals ?? Reflect.get(request, clientLocalsSymbol);
74
75
  if (locals === void 0) {
75
- locals = {};
76
- Reflect.set(request, clientLocalsSymbol, locals);
76
+ _locals = {};
77
77
  }
78
- if (typeof locals !== "object") {
78
+ if (typeof _locals !== "object") {
79
79
  throw new AstroError(AstroErrorData.LocalsNotAnObject);
80
80
  }
81
- return locals;
81
+ return _locals;
82
82
  },
83
83
  set locals(_) {
84
84
  throw new AstroError(AstroErrorData.LocalsReassigned);
@@ -27,5 +27,5 @@ export interface CreateRequestOptions {
27
27
  *
28
28
  * This is used by the static build to create fake requests for prerendering, and by the dev server to convert node requests into the standard request object.
29
29
  */
30
- export declare function createRequest({ url, headers, method, body, logger, locals, isPrerendered, routePattern, }: CreateRequestOptions): Request;
30
+ export declare function createRequest({ url, headers, method, body, logger, isPrerendered, routePattern, }: CreateRequestOptions): Request;
31
31
  export {};
@@ -1,11 +1,9 @@
1
- const clientLocalsSymbol = Symbol.for("astro.locals");
2
1
  function createRequest({
3
2
  url,
4
3
  headers,
5
4
  method = "GET",
6
5
  body = void 0,
7
6
  logger,
8
- locals,
9
7
  isPrerendered = false,
10
8
  routePattern
11
9
  }) {
@@ -43,7 +41,6 @@ function createRequest({
43
41
  }
44
42
  });
45
43
  }
46
- Reflect.set(request, clientLocalsSymbol, locals ?? {});
47
44
  return request;
48
45
  }
49
46
  export {
package/dist/core/util.js CHANGED
@@ -2,7 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from "./constants.js";
5
- import { removeTrailingForwardSlash, slash } from "./path.js";
5
+ import { removeQueryString, removeTrailingForwardSlash, slash } from "./path.js";
6
6
  function isObject(value) {
7
7
  return typeof value === "object" && value != null;
8
8
  }
@@ -10,9 +10,10 @@ function isURL(value) {
10
10
  return Object.prototype.toString.call(value) === "[object URL]";
11
11
  }
12
12
  function isMarkdownFile(fileId, option) {
13
+ const id = removeQueryString(fileId);
13
14
  const _suffix = option?.suffix ?? "";
14
15
  for (let markdownFileExtension of SUPPORTED_MARKDOWN_FILE_EXTENSIONS) {
15
- if (fileId.endsWith(`${markdownFileExtension}${_suffix}`)) return true;
16
+ if (id.endsWith(`${markdownFileExtension}${_suffix}`)) return true;
16
17
  }
17
18
  return false;
18
19
  }
@@ -0,0 +1,6 @@
1
+ import type { AstroConfig } from '../types/public/index.js';
2
+ export declare const createEnvLoader: () => {
3
+ load: (mode: string, config: AstroConfig) => Record<string, string>;
4
+ getPrivateEnv: () => Record<string, string>;
5
+ };
6
+ export type EnvLoader = ReturnType<typeof createEnvLoader>;
@@ -0,0 +1,45 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import { loadEnv } from "vite";
3
+ const isValidIdentifierRe = /^[_$a-zA-Z][\w$]*$/;
4
+ function getPrivateEnv(fullEnv, astroConfig) {
5
+ const viteConfig = astroConfig.vite;
6
+ let envPrefixes = ["PUBLIC_"];
7
+ if (viteConfig.envPrefix) {
8
+ envPrefixes = Array.isArray(viteConfig.envPrefix) ? viteConfig.envPrefix : [viteConfig.envPrefix];
9
+ }
10
+ const privateEnv = {};
11
+ for (const key in fullEnv) {
12
+ if (isValidIdentifierRe.test(key) && envPrefixes.every((prefix) => !key.startsWith(prefix))) {
13
+ if (typeof process.env[key] !== "undefined") {
14
+ let value = process.env[key];
15
+ if (typeof value !== "string") {
16
+ value = `${value}`;
17
+ }
18
+ if (value === "0" || value === "1" || value === "true" || value === "false") {
19
+ privateEnv[key] = value;
20
+ } else {
21
+ privateEnv[key] = `process.env.${key}`;
22
+ }
23
+ } else {
24
+ privateEnv[key] = JSON.stringify(fullEnv[key]);
25
+ }
26
+ }
27
+ }
28
+ return privateEnv;
29
+ }
30
+ const createEnvLoader = () => {
31
+ let privateEnv = {};
32
+ return {
33
+ load: (mode, config) => {
34
+ const loaded = loadEnv(mode, config.vite.envDir ?? fileURLToPath(config.root), "");
35
+ privateEnv = getPrivateEnv(loaded, config);
36
+ return loaded;
37
+ },
38
+ getPrivateEnv: () => {
39
+ return privateEnv;
40
+ }
41
+ };
42
+ };
43
+ export {
44
+ createEnvLoader
45
+ };
@@ -2,8 +2,8 @@ import { AstroError } from '../core/errors/index.js';
2
2
  import type { ValidationResultInvalid } from './validators.js';
3
3
  export { validateEnvVariable, getEnvFieldType } from './validators.js';
4
4
  export type GetEnv = (key: string) => string | undefined;
5
- type OnSetGetEnv = (reset: boolean) => void;
6
- export declare function setGetEnv(fn: GetEnv, reset?: boolean): void;
5
+ type OnSetGetEnv = () => void;
6
+ export declare function setGetEnv(fn: GetEnv): void;
7
7
  export declare function setOnSetGetEnv(fn: OnSetGetEnv): void;
8
8
  export declare function getEnv(...args: Parameters<GetEnv>): string | undefined;
9
9
  export declare function createInvalidVariablesError(key: string, type: string, result: ValidationResultInvalid): AstroError;
@@ -2,9 +2,9 @@ import { AstroError, AstroErrorData } from "../core/errors/index.js";
2
2
  import { invalidVariablesToError } from "./errors.js";
3
3
  import { validateEnvVariable, getEnvFieldType } from "./validators.js";
4
4
  let _getEnv = (key) => process.env[key];
5
- function setGetEnv(fn, reset = false) {
5
+ function setGetEnv(fn) {
6
6
  _getEnv = fn;
7
- _onSetGetEnv(reset);
7
+ _onSetGetEnv();
8
8
  }
9
9
  let _onSetGetEnv = () => {
10
10
  };
@@ -1,9 +1,11 @@
1
- import { type Plugin } from 'vite';
1
+ import type { Plugin } from 'vite';
2
2
  import type { AstroSettings } from '../types/astro.js';
3
+ import type { EnvLoader } from './env-loader.js';
3
4
  interface AstroEnvPluginParams {
4
5
  settings: AstroSettings;
5
6
  mode: string;
6
7
  sync: boolean;
8
+ envLoader: EnvLoader;
7
9
  }
8
- export declare function astroEnv({ settings, mode, sync }: AstroEnvPluginParams): Plugin;
10
+ export declare function astroEnv({ settings, mode, sync, envLoader }: AstroEnvPluginParams): Plugin;
9
11
  export {};
@@ -1,6 +1,4 @@
1
1
  import { readFileSync } from "node:fs";
2
- import { fileURLToPath } from "node:url";
3
- import { loadEnv } from "vite";
4
2
  import { AstroError, AstroErrorData } from "../core/errors/index.js";
5
3
  import {
6
4
  MODULE_TEMPLATE_URL,
@@ -9,17 +7,23 @@ import {
9
7
  } from "./constants.js";
10
8
  import { invalidVariablesToError } from "./errors.js";
11
9
  import { getEnvFieldType, validateEnvVariable } from "./validators.js";
12
- function astroEnv({ settings, mode, sync }) {
10
+ function astroEnv({ settings, mode, sync, envLoader }) {
13
11
  const { schema, validateSecrets } = settings.config.env;
12
+ let isDev;
14
13
  let templates = null;
15
14
  return {
16
15
  name: "astro-env-plugin",
17
16
  enforce: "pre",
17
+ config(_, { command }) {
18
+ isDev = command !== "build";
19
+ },
18
20
  buildStart() {
19
- const loadedEnv = loadEnv(mode, fileURLToPath(settings.config.root), "");
20
- for (const [key, value] of Object.entries(loadedEnv)) {
21
- if (value !== void 0) {
22
- process.env[key] = value;
21
+ const loadedEnv = envLoader.load(mode, settings.config);
22
+ if (!isDev) {
23
+ for (const [key, value] of Object.entries(loadedEnv)) {
24
+ if (value !== void 0) {
25
+ process.env[key] = value;
26
+ }
23
27
  }
24
28
  }
25
29
  const validatedVariables = validatePublicVariables({
@@ -29,7 +33,7 @@ function astroEnv({ settings, mode, sync }) {
29
33
  sync
30
34
  });
31
35
  templates = {
32
- ...getTemplates(schema, validatedVariables),
36
+ ...getTemplates(schema, validatedVariables, isDev ? loadedEnv : null),
33
37
  internal: `export const schema = ${JSON.stringify(schema)};`
34
38
  };
35
39
  },
@@ -92,7 +96,7 @@ function validatePublicVariables({
92
96
  }
93
97
  return valid;
94
98
  }
95
- function getTemplates(schema, validatedVariables) {
99
+ function getTemplates(schema, validatedVariables, loadedEnv) {
96
100
  let client = "";
97
101
  let server = readFileSync(MODULE_TEMPLATE_URL, "utf-8");
98
102
  let onSetGetEnv = "";
@@ -110,10 +114,15 @@ function getTemplates(schema, validatedVariables) {
110
114
  }
111
115
  server += `export let ${key} = _internalGetSecret(${JSON.stringify(key)});
112
116
  `;
113
- onSetGetEnv += `${key} = reset ? undefined : _internalGetSecret(${JSON.stringify(key)});
117
+ onSetGetEnv += `${key} = _internalGetSecret(${JSON.stringify(key)});
114
118
  `;
115
119
  }
116
120
  server = server.replace("// @@ON_SET_GET_ENV@@", onSetGetEnv);
121
+ if (loadedEnv) {
122
+ server = server.replace("// @@GET_ENV@@", `return (${JSON.stringify(loadedEnv)})[key];`);
123
+ } else {
124
+ server = server.replace("// @@GET_ENV@@", "return _getEnv(key);");
125
+ }
117
126
  return {
118
127
  client,
119
128
  server
@@ -150,7 +150,6 @@ function createDevelopmentManifest(settings) {
150
150
  inlinedScripts: /* @__PURE__ */ new Map(),
151
151
  i18n: i18nManifest,
152
152
  checkOrigin: (settings.config.security?.checkOrigin && settings.buildOutput === "server") ?? false,
153
- envGetSecretEnabled: false,
154
153
  key: hasEnvironmentKey() ? getEnvironmentKey() : createKey(),
155
154
  middleware() {
156
155
  return {
@@ -176,7 +176,7 @@ async function handleRoute({
176
176
  const fourOhFourRoute = await matchRoute("/404", manifestData, pipeline);
177
177
  if (fourOhFourRoute) {
178
178
  renderContext = await RenderContext.create({
179
- locals,
179
+ locals: {},
180
180
  pipeline,
181
181
  pathname,
182
182
  middleware: isDefaultPrerendered404(fourOhFourRoute.route) ? void 0 : middleware,
@@ -1,7 +1,7 @@
1
1
  import type * as vite from 'vite';
2
- import type { AstroSettings } from '../types/astro.js';
2
+ import type { EnvLoader } from '../env/env-loader.js';
3
3
  interface EnvPluginOptions {
4
- settings: AstroSettings;
4
+ envLoader: EnvLoader;
5
5
  }
6
- export default function envVitePlugin({ settings }: EnvPluginOptions): vite.Plugin;
6
+ export default function envVitePlugin({ envLoader }: EnvPluginOptions): vite.Plugin;
7
7
  export {};
@@ -1,39 +1,6 @@
1
- import { fileURLToPath } from "node:url";
2
1
  import { transform } from "esbuild";
3
2
  import MagicString from "magic-string";
4
- import { loadEnv } from "vite";
5
3
  const importMetaEnvOnlyRe = /\bimport\.meta\.env\b(?!\.)/;
6
- const isValidIdentifierRe = /^[_$a-zA-Z][\w$]*$/;
7
- function getPrivateEnv(viteConfig, astroConfig) {
8
- let envPrefixes = ["PUBLIC_"];
9
- if (viteConfig.envPrefix) {
10
- envPrefixes = Array.isArray(viteConfig.envPrefix) ? viteConfig.envPrefix : [viteConfig.envPrefix];
11
- }
12
- const fullEnv = loadEnv(
13
- viteConfig.mode,
14
- viteConfig.envDir ?? fileURLToPath(astroConfig.root),
15
- ""
16
- );
17
- const privateEnv = {};
18
- for (const key in fullEnv) {
19
- if (isValidIdentifierRe.test(key) && envPrefixes.every((prefix) => !key.startsWith(prefix))) {
20
- if (typeof process.env[key] !== "undefined") {
21
- let value = process.env[key];
22
- if (typeof value !== "string") {
23
- value = `${value}`;
24
- }
25
- if (value === "0" || value === "1" || value === "true" || value === "false") {
26
- privateEnv[key] = value;
27
- } else {
28
- privateEnv[key] = `process.env.${key}`;
29
- }
30
- } else {
31
- privateEnv[key] = JSON.stringify(fullEnv[key]);
32
- }
33
- }
34
- }
35
- return privateEnv;
36
- }
37
4
  function getReferencedPrivateKeys(source, privateEnv) {
38
5
  const references = /* @__PURE__ */ new Set();
39
6
  for (const key in privateEnv) {
@@ -70,13 +37,12 @@ async function replaceDefine(code, id, define, config) {
70
37
  map: result.map || null
71
38
  };
72
39
  }
73
- function envVitePlugin({ settings }) {
40
+ function envVitePlugin({ envLoader }) {
74
41
  let privateEnv;
75
42
  let defaultDefines;
76
43
  let isDev;
77
44
  let devImportMetaEnvPrepend;
78
45
  let viteConfig;
79
- const { config: astroConfig } = settings;
80
46
  return {
81
47
  name: "astro:vite-plugin-env",
82
48
  config(_, { command }) {
@@ -102,7 +68,7 @@ function envVitePlugin({ settings }) {
102
68
  if (!options?.ssr || !source.includes("import.meta.env")) {
103
69
  return;
104
70
  }
105
- privateEnv ??= getPrivateEnv(viteConfig, astroConfig);
71
+ privateEnv ??= envLoader.getPrivateEnv();
106
72
  if (isDev) {
107
73
  const s = new MagicString(source);
108
74
  if (!devImportMetaEnvPrepend) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "5.0.3",
3
+ "version": "5.0.5",
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",
@@ -159,7 +159,7 @@
159
159
  "zod-to-json-schema": "^3.23.5",
160
160
  "zod-to-ts": "^1.2.0",
161
161
  "@astrojs/internal-helpers": "0.4.2",
162
- "@astrojs/markdown-remark": "6.0.0",
162
+ "@astrojs/markdown-remark": "6.0.1",
163
163
  "@astrojs/telemetry": "3.2.0"
164
164
  },
165
165
  "optionalDependencies": {
package/templates/env.mjs CHANGED
@@ -1,13 +1,22 @@
1
1
  // @ts-check
2
2
  import { schema } from 'virtual:astro:env/internal';
3
3
  import {
4
+ getEnv as _getEnv,
4
5
  createInvalidVariablesError,
5
- getEnv,
6
6
  getEnvFieldType,
7
7
  setOnSetGetEnv,
8
8
  validateEnvVariable,
9
9
  } from 'astro/env/runtime';
10
10
 
11
+ // @ts-expect-error
12
+ /** @returns {string} */
13
+ // used while generating the virtual module
14
+ // biome-ignore lint/correctness/noUnusedFunctionParameters: `key` is used by the generated code
15
+ // biome-ignore lint/correctness/noUnusedVariables: `key` is used by the generated code
16
+ const getEnv = (key) => {
17
+ // @@GET_ENV@@
18
+ };
19
+
11
20
  export const getSecret = (key) => {
12
21
  return getEnv(key);
13
22
  };
@@ -25,9 +34,6 @@ const _internalGetSecret = (key) => {
25
34
  throw createInvalidVariablesError(key, type, result);
26
35
  };
27
36
 
28
- // used while generating the virtual module
29
- // biome-ignore lint/correctness/noUnusedFunctionParameters: `reset` is used by the generated code
30
- // biome-ignore lint/correctness/noUnusedVariables: `reset` is used by the generated code
31
- setOnSetGetEnv((reset) => {
37
+ setOnSetGetEnv(() => {
32
38
  // @@ON_SET_GET_ENV@@
33
39
  });