astro 5.3.0 → 5.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38,6 +38,7 @@ function createManifest(manifest, renderers, middleware) {
38
38
  clientDirectives: manifest?.clientDirectives ?? getDefaultClientDirectives(),
39
39
  renderers: renderers ?? manifest?.renderers ?? [],
40
40
  base: manifest?.base ?? ASTRO_CONFIG_DEFAULTS.base,
41
+ userAssetsBase: manifest?.userAssetsBase ?? "",
41
42
  componentMetadata: manifest?.componentMetadata ?? /* @__PURE__ */ new Map(),
42
43
  inlinedScripts: manifest?.inlinedScripts ?? /* @__PURE__ */ new Map(),
43
44
  i18n: manifest?.i18n,
@@ -153,7 +153,7 @@ ${contentConfig.error.message}`);
153
153
  logger.info("Content config changed");
154
154
  shouldClear = true;
155
155
  }
156
- if (previousAstroVersion && previousAstroVersion !== "5.3.0") {
156
+ if (previousAstroVersion && previousAstroVersion !== "5.3.1") {
157
157
  logger.info("Astro version changed");
158
158
  shouldClear = true;
159
159
  }
@@ -161,8 +161,8 @@ ${contentConfig.error.message}`);
161
161
  logger.info("Clearing content store");
162
162
  this.#store.clearAll();
163
163
  }
164
- if ("5.3.0") {
165
- await this.#store.metaStore().set("astro-version", "5.3.0");
164
+ if ("5.3.1") {
165
+ await this.#store.metaStore().set("astro-version", "5.3.1");
166
166
  }
167
167
  if (currentConfigDigest) {
168
168
  await this.#store.metaStore().set("content-config-digest", currentConfigDigest);
@@ -1,10 +1,10 @@
1
1
  import { promises as fs, existsSync } from "node:fs";
2
2
  import { relative } from "node:path";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
- import fastGlob from "fast-glob";
5
4
  import { bold, green } from "kleur/colors";
6
- import micromatch from "micromatch";
7
5
  import pLimit from "p-limit";
6
+ import picomatch from "picomatch";
7
+ import { glob as tinyglobby } from "tinyglobby";
8
8
  import { getContentEntryIdAndSlug, posixRelative } from "../utils.js";
9
9
  function generateIdDefault({ entry, base, data }) {
10
10
  if (data.slug) {
@@ -154,8 +154,9 @@ function glob(globOptions) {
154
154
  if (!exists) {
155
155
  logger.warn(`The base directory "${fileURLToPath(baseDir)}" does not exist.`);
156
156
  }
157
- const files = await fastGlob(globOptions.pattern, {
158
- cwd: fileURLToPath(baseDir)
157
+ const files = await tinyglobby(globOptions.pattern, {
158
+ cwd: fileURLToPath(baseDir),
159
+ expandDirectories: false
159
160
  });
160
161
  if (exists && files.length === 0) {
161
162
  logger.warn(
@@ -220,7 +221,7 @@ function glob(globOptions) {
220
221
  return;
221
222
  }
222
223
  watcher.add(filePath);
223
- const matchesGlob = (entry) => !entry.startsWith("../") && micromatch.isMatch(entry, globOptions.pattern);
224
+ const matchesGlob = (entry) => !entry.startsWith("../") && picomatch.isMatch(entry, globOptions.pattern);
224
225
  const basePath = fileURLToPath(baseDir);
225
226
  async function onChange(changedPath) {
226
227
  const entry = posixRelative(basePath, changedPath);
@@ -4,8 +4,8 @@ export declare function createImage(pluginContext: PluginContext, shouldEmitFile
4
4
  ASTRO_ASSET: string;
5
5
  width: number;
6
6
  height: number;
7
- format: import("../assets/types.js").ImageInputFormat;
8
7
  src: string;
8
+ format: import("../assets/types.js").ImageInputFormat;
9
9
  fsPath: string;
10
10
  orientation?: number | undefined;
11
11
  }, string>;
@@ -1,7 +1,7 @@
1
1
  import * as path from "node:path";
2
2
  import { fileURLToPath, pathToFileURL } from "node:url";
3
- import glob from "fast-glob";
4
3
  import { bold, cyan } from "kleur/colors";
4
+ import { glob } from "tinyglobby";
5
5
  import { normalizePath } from "vite";
6
6
  import { z } from "zod";
7
7
  import { zodToJsonSchema } from "zod-to-json-schema";
@@ -48,20 +48,15 @@ async function createContentTypesGenerator({
48
48
  }
49
49
  const globResult = await glob("**", {
50
50
  cwd: fileURLToPath(contentPaths.contentDir),
51
- fs: {
52
- readdir: fs.readdir.bind(fs),
53
- readdirSync: fs.readdirSync.bind(fs)
54
- },
55
- onlyFiles: false,
56
- objectMode: true
51
+ absolute: true
57
52
  });
58
- for (const entry of globResult) {
59
- const fullPath = path.join(fileURLToPath(contentPaths.contentDir), entry.path);
53
+ for (const fullPath of globResult) {
60
54
  const entryURL = pathToFileURL(fullPath);
61
55
  if (entryURL.href.startsWith(contentPaths.config.url.href)) continue;
62
- if (entry.dirent.isFile()) {
56
+ const stat = fs.statSync(fullPath);
57
+ if (stat.isFile()) {
63
58
  events.push({ name: "add", entry: entryURL });
64
- } else if (entry.dirent.isDirectory()) {
59
+ } else if (stat.isDirectory()) {
65
60
  events.push({ name: "addDir", entry: entryURL });
66
61
  }
67
62
  }
@@ -2,8 +2,8 @@ import nodeFs from "node:fs";
2
2
  import { extname } from "node:path";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
4
  import { dataToEsm } from "@rollup/pluginutils";
5
- import glob from "fast-glob";
6
5
  import pLimit from "p-limit";
6
+ import { glob } from "tinyglobby";
7
7
  import { AstroError, AstroErrorData } from "../core/errors/index.js";
8
8
  import { rootRelativePath } from "../core/viteUtils.js";
9
9
  import { createDefaultAstroMetadata } from "../vite-plugin-astro/metadata.js";
@@ -225,7 +225,7 @@ async function generateLookupMap({
225
225
  {
226
226
  absolute: true,
227
227
  cwd: fileURLToPath(root),
228
- fs
228
+ expandDirectories: false
229
229
  }
230
230
  );
231
231
  const limit = pLimit(10);
@@ -38,6 +38,13 @@ export type SSRManifest = {
38
38
  routes: RouteInfo[];
39
39
  site?: string;
40
40
  base: string;
41
+ /**
42
+ * The base of the assets generated **by the user**. For example, scripts created by the user falls under this category.
43
+ *
44
+ * The value of this field comes from `vite.base`. We aren't usually this tight to vite in our code base, so probably
45
+ * this should be refactored somehow.
46
+ */
47
+ userAssetsBase: string | undefined;
41
48
  trailingSlash: AstroConfig['trailingSlash'];
42
49
  buildFormat: NonNullable<AstroConfig['build']>['format'];
43
50
  compressHTML: boolean;
@@ -388,6 +388,7 @@ function createBuildManifest(settings, internals, renderers, middleware, key) {
388
388
  compressHTML: settings.config.compressHTML,
389
389
  renderers,
390
390
  base: settings.config.base,
391
+ userAssetsBase: settings.config?.vite?.base,
391
392
  assetsPrefix: settings.config.build.assetsPrefix,
392
393
  site: settings.config.site,
393
394
  componentMetadata: internals.componentMetadata,
@@ -1,5 +1,5 @@
1
1
  import { fileURLToPath } from "node:url";
2
- import glob from "fast-glob";
2
+ import { glob } from "tinyglobby";
3
3
  import { getAssetsPrefix } from "../../../assets/utils/getAssetsPrefix.js";
4
4
  import { normalizeTheLocale } from "../../../i18n/index.js";
5
5
  import { toFallbackType, toRoutingStrategy } from "../../../i18n/utils.js";
@@ -216,6 +216,7 @@ function buildManifest(opts, internals, staticFiles, encodedKey) {
216
216
  routes,
217
217
  site: settings.config.site,
218
218
  base: settings.config.base,
219
+ userAssetsBase: settings.config?.vite?.base,
219
220
  trailingSlash: settings.config.trailingSlash,
220
221
  compressHTML: settings.config.compressHTML,
221
222
  assetsPrefix: settings.config.build.assetsPrefix,
@@ -6,7 +6,6 @@ export declare function viteBuild(opts: StaticBuildOptions): Promise<{
6
6
  ssrOutputChunkNames: string[];
7
7
  }>;
8
8
  export declare function staticBuild(opts: StaticBuildOptions, internals: BuildInternals, ssrOutputChunkNames: string[]): Promise<void>;
9
- export declare function copyFiles(fromFolder: URL, toFolder: URL, includeDotfiles?: boolean): Promise<void[] | undefined>;
10
9
  /**
11
10
  * This function takes the virtual module name of any page entrypoint and
12
11
  * transforms it to generate a final `.mjs` output file.
@@ -2,8 +2,8 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
4
  import { teardown } from "@astrojs/compiler";
5
- import glob from "fast-glob";
6
5
  import { bgGreen, black, green } from "kleur/colors";
6
+ import { glob } from "tinyglobby";
7
7
  import * as vite from "vite";
8
8
  import { createBuildInternals } from "../../core/build/internal.js";
9
9
  import { emptyDir, removeEmptyDirs } from "../../core/fs/index.js";
@@ -185,8 +185,8 @@ async function clientBuild(opts, internals, input, container) {
185
185
  const ssr = settings.buildOutput === "server";
186
186
  const out = ssr ? settings.config.build.client : getOutDirWithinCwd(settings.config.outDir);
187
187
  if (!input.size) {
188
- if (ssr) {
189
- await copyFiles(settings.config.publicDir, out, true);
188
+ if (ssr && fs.existsSync(settings.config.publicDir)) {
189
+ await fs.promises.cp(settings.config.publicDir, out, { recursive: true, force: true });
190
190
  }
191
191
  return null;
192
192
  }
@@ -283,29 +283,11 @@ async function cleanServerOutput(opts, ssrOutputChunkNames, internals) {
283
283
  await Promise.all(
284
284
  fileNames.filter((fileName) => fileName.endsWith(".d.ts")).map((fileName) => fs.promises.rm(new URL(fileName, out)))
285
285
  );
286
- await copyFiles(out, opts.settings.config.outDir, true);
286
+ await fs.promises.cp(out, opts.settings.config.outDir, { recursive: true, force: true });
287
287
  await fs.promises.rm(out, { recursive: true });
288
288
  return;
289
289
  }
290
290
  }
291
- async function copyFiles(fromFolder, toFolder, includeDotfiles = false) {
292
- const files = await glob("**/*", {
293
- cwd: fileURLToPath(fromFolder),
294
- dot: includeDotfiles
295
- });
296
- if (files.length === 0) return;
297
- return await Promise.all(
298
- files.map(async function copyFile(filename) {
299
- const from = new URL(filename, fromFolder);
300
- const to = new URL(filename, toFolder);
301
- const lastFolder = new URL("./", to);
302
- return fs.promises.mkdir(lastFolder, { recursive: true }).then(async function fsCopyFile() {
303
- const p = await fs.promises.copyFile(from, to, fs.constants.COPYFILE_FICLONE);
304
- return p;
305
- });
306
- })
307
- );
308
- }
309
291
  async function ssrMoveAssets(opts) {
310
292
  opts.logger.info("build", "Rearranging server assets...");
311
293
  const serverRoot = opts.settings.buildOutput === "static" ? opts.settings.config.build.client : opts.settings.config.build.server;
@@ -336,7 +318,6 @@ function makeAstroPageEntryPointFileName(prefix, facadeModuleId, routes) {
336
318
  return `pages${name.replace(/\/$/, "/index").replaceAll(/[[\]]/g, "_").replaceAll("...", "---")}.astro.mjs`;
337
319
  }
338
320
  export {
339
- copyFiles,
340
321
  makeAstroPageEntryPointFileName,
341
322
  staticBuild,
342
323
  viteBuild
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "5.3.0";
1
+ const ASTRO_VERSION = "5.3.1";
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";
@@ -1,6 +1,6 @@
1
1
  import nodeFs from "node:fs";
2
2
  import { fileURLToPath } from "node:url";
3
- import glob from "fast-glob";
3
+ import { convertPathToPattern } from "tinyglobby";
4
4
  import * as vite from "vite";
5
5
  import { crawlFrameworkPkgs } from "vitefu";
6
6
  import { vitePluginActions, vitePluginUserActions } from "../actions/plugins.js";
@@ -84,7 +84,7 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
84
84
  }
85
85
  }
86
86
  });
87
- const srcDirPattern = glob.convertPathToPattern(fileURLToPath(settings.config.srcDir));
87
+ const srcDirPattern = convertPathToPattern(fileURLToPath(settings.config.srcDir));
88
88
  const envLoader = createEnvLoader(mode, settings.config);
89
89
  const commonConfig = {
90
90
  // Tell Vite not to combine config from vite.config.js with our provided inline config
@@ -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.3.0";
25
+ const currentVersion = "5.3.1";
26
26
  const isPrerelease = currentVersion.includes("-");
27
27
  if (!isPrerelease) {
28
28
  try {
@@ -38,7 +38,7 @@ function serverStart({
38
38
  host,
39
39
  base
40
40
  }) {
41
- const version = "5.3.0";
41
+ const version = "5.3.1";
42
42
  const localPrefix = `${dim("\u2503")} Local `;
43
43
  const networkPrefix = `${dim("\u2503")} Network `;
44
44
  const emptyPrefix = " ".repeat(11);
@@ -281,7 +281,7 @@ function printHelp({
281
281
  message.push(
282
282
  linebreak(),
283
283
  ` ${bgGreen(black(` ${commandName} `))} ${green(
284
- `v${"5.3.0"}`
284
+ `v${"5.3.1"}`
285
285
  )} ${headline}`
286
286
  );
287
287
  }
@@ -316,6 +316,7 @@ class RenderContext {
316
316
  };
317
317
  const result = {
318
318
  base: manifest.base,
319
+ userAssetsBase: manifest.userAssetsBase,
319
320
  cancelled: false,
320
321
  clientDirectives,
321
322
  inlinedScripts,
@@ -1,7 +1,12 @@
1
1
  import { shouldAppendForwardSlash } from "../build/util.js";
2
2
  import { originPathnameSymbol } from "../constants.js";
3
3
  import { AstroError, AstroErrorData } from "../errors/index.js";
4
- import { appendForwardSlash, removeTrailingForwardSlash } from "../path.js";
4
+ import {
5
+ appendForwardSlash,
6
+ joinPaths,
7
+ prependForwardSlash,
8
+ removeTrailingForwardSlash
9
+ } from "../path.js";
5
10
  import { createRequest } from "../request.js";
6
11
  import { DEFAULT_404_ROUTE } from "./astro-designed-error-pages.js";
7
12
  function findRouteToRewrite({
@@ -21,10 +26,18 @@ function findRouteToRewrite({
21
26
  newUrl = new URL(payload, new URL(request.url).origin);
22
27
  }
23
28
  let pathname = newUrl.pathname;
29
+ const shouldAppendSlash = shouldAppendForwardSlash(trailingSlash, buildFormat);
24
30
  if (base !== "/" && newUrl.pathname.startsWith(base)) {
25
- pathname = shouldAppendForwardSlash(trailingSlash, buildFormat) ? appendForwardSlash(newUrl.pathname) : removeTrailingForwardSlash(newUrl.pathname);
31
+ pathname = shouldAppendSlash ? appendForwardSlash(newUrl.pathname) : removeTrailingForwardSlash(newUrl.pathname);
26
32
  pathname = pathname.slice(base.length);
27
33
  }
34
+ if (!pathname.startsWith("/") && shouldAppendSlash && newUrl.pathname.endsWith("/")) {
35
+ pathname = prependForwardSlash(pathname);
36
+ }
37
+ if (pathname === "/" && base !== "/" && !shouldAppendSlash) {
38
+ pathname = "";
39
+ }
40
+ newUrl.pathname = joinPaths(...[base, pathname].filter(Boolean));
28
41
  const decodedPathname = decodeURI(pathname);
29
42
  let foundRoute;
30
43
  for (const route of routes) {
@@ -13,6 +13,9 @@ function renderAllHeadContent(result) {
13
13
  );
14
14
  result.styles.clear();
15
15
  const scripts = Array.from(result.scripts).filter(uniqueElements).map((script) => {
16
+ if (result.userAssetsBase) {
17
+ script.props.src = (result.base === "/" ? "" : result.base) + result.userAssetsBase + script.props.src;
18
+ }
16
19
  return renderElement("script", script, false);
17
20
  });
18
21
  const links = Array.from(result.links).filter(uniqueElements).map((link) => renderElement("link", link, false));
@@ -11,7 +11,9 @@ async function renderScript(result, id) {
11
11
  }
12
12
  }
13
13
  const resolved = await result.resolve(id);
14
- return markHTMLString(`<script type="module" src="${resolved}"></script>`);
14
+ return markHTMLString(
15
+ `<script type="module" src="${result.userAssetsBase ? (result.base === "/" ? "" : result.base) + result.userAssetsBase : ""}${resolved}"></script>`
16
+ );
15
17
  }
16
18
  export {
17
19
  renderScript
@@ -195,6 +195,7 @@ export interface SSRResult {
195
195
  */
196
196
  cancelled: boolean;
197
197
  base: string;
198
+ userAssetsBase: string | undefined;
198
199
  styles: Set<SSRElement>;
199
200
  scripts: Set<SSRElement>;
200
201
  links: Set<SSRElement>;
@@ -150,6 +150,7 @@ function createDevelopmentManifest(settings) {
150
150
  clientDirectives: settings.clientDirectives,
151
151
  renderers: [],
152
152
  base: settings.config.base,
153
+ userAssetsBase: settings.config?.vite?.base,
153
154
  assetsPrefix: settings.config.build.assetsPrefix,
154
155
  site: settings.config.site,
155
156
  componentMetadata: /* @__PURE__ */ new Map(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "5.3.0",
3
+ "version": "5.3.1",
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",
@@ -125,7 +125,6 @@
125
125
  "es-module-lexer": "^1.6.0",
126
126
  "esbuild": "^0.24.2",
127
127
  "estree-walker": "^3.0.3",
128
- "fast-glob": "^3.3.3",
129
128
  "flattie": "^1.1.1",
130
129
  "github-slugger": "^2.0.0",
131
130
  "html-escaper": "3.0.3",
@@ -134,17 +133,18 @@
134
133
  "kleur": "^4.1.5",
135
134
  "magic-string": "^0.30.17",
136
135
  "magicast": "^0.3.5",
137
- "micromatch": "^4.0.8",
138
136
  "mrmime": "^2.0.0",
139
137
  "neotraverse": "^0.6.18",
140
138
  "p-limit": "^6.2.0",
141
139
  "p-queue": "^8.1.0",
140
+ "picomatch": "^4.0.2",
142
141
  "preferred-pm": "^4.1.1",
143
142
  "prompts": "^2.4.2",
144
143
  "rehype": "^13.0.2",
145
144
  "semver": "^7.7.1",
146
145
  "shiki": "^1.29.2",
147
146
  "tinyexec": "^0.3.2",
147
+ "tinyglobby": "^0.2.12",
148
148
  "tsconfck": "^3.1.4",
149
149
  "ultrahtml": "^1.5.3",
150
150
  "unist-util-visit": "^5.0.0",
@@ -159,9 +159,9 @@
159
159
  "zod": "^3.24.1",
160
160
  "zod-to-json-schema": "^3.24.1",
161
161
  "zod-to-ts": "^1.2.0",
162
+ "@astrojs/internal-helpers": "0.5.1",
162
163
  "@astrojs/markdown-remark": "6.1.0",
163
- "@astrojs/telemetry": "3.2.0",
164
- "@astrojs/internal-helpers": "0.5.1"
164
+ "@astrojs/telemetry": "3.2.0"
165
165
  },
166
166
  "optionalDependencies": {
167
167
  "sharp": "^0.33.3"
@@ -179,7 +179,7 @@
179
179
  "@types/html-escaper": "3.0.4",
180
180
  "@types/http-cache-semantics": "^4.0.4",
181
181
  "@types/js-yaml": "^4.0.9",
182
- "@types/micromatch": "^4.0.9",
182
+ "@types/picomatch": "^3.0.2",
183
183
  "@types/prompts": "^2.4.9",
184
184
  "@types/semver": "^7.5.8",
185
185
  "@types/yargs-parser": "^21.0.3",