astro 7.2.9 → 7.2.10
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/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/content/content-layer.js +3 -3
- package/dist/content/data-store-writer.d.ts +18 -5
- package/dist/content/data-store-writer.js +11 -3
- package/dist/content/index.d.ts +1 -1
- package/dist/content/index.js +5 -1
- package/dist/content/mutable-data-store.d.ts +11 -0
- package/dist/content/mutable-data-store.js +31 -1
- package/dist/content/runtime.js +3 -1
- package/dist/content/vite-plugin-content-virtual-mod.d.ts +11 -1
- package/dist/content/vite-plugin-content-virtual-mod.js +36 -3
- package/dist/core/app/entrypoints/virtual/dev.js +2 -2
- package/dist/core/build/generate.js +19 -25
- package/dist/core/build/plugins/plugin-manifest.js +1 -1
- package/dist/core/cache/runtime/cache.js +3 -0
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +4 -2
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/server-islands/vite-plugin-server-islands.js +2 -2
- package/dist/core/util.d.ts +0 -9
- package/dist/core/util.js +0 -34
- package/dist/core/viteUtils.d.ts +1 -13
- package/dist/core/viteUtils.js +3 -33
- package/dist/vite-plugin-app/createAstroServerApp.js +1 -1
- package/package.json +5 -5
|
@@ -196,7 +196,7 @@ ${contentConfig.error.message}`
|
|
|
196
196
|
logger.info("Content config changed");
|
|
197
197
|
shouldClear = true;
|
|
198
198
|
}
|
|
199
|
-
if (previousAstroVersion && previousAstroVersion !== "7.2.
|
|
199
|
+
if (previousAstroVersion && previousAstroVersion !== "7.2.10") {
|
|
200
200
|
logger.info("Astro version changed");
|
|
201
201
|
shouldClear = true;
|
|
202
202
|
}
|
|
@@ -204,8 +204,8 @@ ${contentConfig.error.message}`
|
|
|
204
204
|
logger.info("Clearing content store");
|
|
205
205
|
this.#store.clearAll();
|
|
206
206
|
}
|
|
207
|
-
if ("7.2.
|
|
208
|
-
this.#store.metaStore().set("astro-version", "7.2.
|
|
207
|
+
if ("7.2.10") {
|
|
208
|
+
this.#store.metaStore().set("astro-version", "7.2.10");
|
|
209
209
|
}
|
|
210
210
|
if (currentConfigDigest) {
|
|
211
211
|
this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
|
@@ -8,8 +8,17 @@ export type DataStoreManifest = Record<string, string[]>;
|
|
|
8
8
|
* (build/dev) and are never imported at runtime.
|
|
9
9
|
*/
|
|
10
10
|
export interface DataStoreWriter {
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Serialize and persist the given collections.
|
|
13
|
+
* Resolves to `true` if the data on disk changed, or `false` if the write
|
|
14
|
+
* was skipped because the persisted data was already identical.
|
|
15
|
+
*/
|
|
16
|
+
write(collections: Map<string, Map<string, any>>): Promise<boolean>;
|
|
17
|
+
/**
|
|
18
|
+
* The file whose write commits a store update: the store file itself, or
|
|
19
|
+
* the manifest for chunked stores.
|
|
20
|
+
*/
|
|
21
|
+
readonly target: PathLike;
|
|
13
22
|
}
|
|
14
23
|
/**
|
|
15
24
|
* Serialize collections to a deterministic devalue string.
|
|
@@ -35,15 +44,18 @@ export declare function chunkString(str: string, maxBytes: number): string[];
|
|
|
35
44
|
* partial reads. If the file already contains identical data, the write is
|
|
36
45
|
* skipped. Callers are responsible for serializing concurrent writes to the
|
|
37
46
|
* same file.
|
|
47
|
+
*
|
|
48
|
+
* Returns `true` if the file was written, or `false` if the write was skipped.
|
|
38
49
|
*/
|
|
39
|
-
export declare function writeFileAtomic(file: PathLike, data: string): Promise<
|
|
50
|
+
export declare function writeFileAtomic(file: PathLike, data: string): Promise<boolean>;
|
|
40
51
|
/**
|
|
41
52
|
* A {@link DataStoreWriter} that serializes the whole store to a single file.
|
|
42
53
|
*/
|
|
43
54
|
export declare class FileWriter implements DataStoreWriter {
|
|
44
55
|
#private;
|
|
45
56
|
constructor(file: PathLike);
|
|
46
|
-
|
|
57
|
+
get target(): PathLike;
|
|
58
|
+
write(collections: Map<string, Map<string, any>>): Promise<boolean>;
|
|
47
59
|
}
|
|
48
60
|
/**
|
|
49
61
|
* A {@link DataStoreWriter} that splits the store across many content-addressed
|
|
@@ -60,5 +72,6 @@ export declare class FileWriter implements DataStoreWriter {
|
|
|
60
72
|
export declare class ChunkedWriter implements DataStoreWriter {
|
|
61
73
|
#private;
|
|
62
74
|
constructor(dir: URL, chunkSize: number);
|
|
63
|
-
|
|
75
|
+
get target(): PathLike;
|
|
76
|
+
write(collections: Map<string, Map<string, any>>): Promise<boolean>;
|
|
64
77
|
}
|
|
@@ -47,18 +47,22 @@ async function writeFileAtomic(file, data) {
|
|
|
47
47
|
const tempFile = file instanceof URL ? new URL(`${file.href}.tmp`) : `${file}.tmp`;
|
|
48
48
|
const oldData = await fs.readFile(file, "utf-8").catch(() => "");
|
|
49
49
|
if (oldData === data) {
|
|
50
|
-
return;
|
|
50
|
+
return false;
|
|
51
51
|
}
|
|
52
52
|
await fs.writeFile(tempFile, data);
|
|
53
53
|
await fs.rename(tempFile, file);
|
|
54
|
+
return true;
|
|
54
55
|
}
|
|
55
56
|
class FileWriter {
|
|
56
57
|
#file;
|
|
57
58
|
constructor(file) {
|
|
58
59
|
this.#file = file;
|
|
59
60
|
}
|
|
61
|
+
get target() {
|
|
62
|
+
return this.#file;
|
|
63
|
+
}
|
|
60
64
|
async write(collections) {
|
|
61
|
-
await writeFileAtomic(this.#file, serializeDataStore(collections));
|
|
65
|
+
return await writeFileAtomic(this.#file, serializeDataStore(collections));
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
class ChunkedWriter {
|
|
@@ -72,6 +76,9 @@ class ChunkedWriter {
|
|
|
72
76
|
this.#manifestFile = new URL(`./${DATA_STORE_MANIFEST_FILE}`, dir);
|
|
73
77
|
this.#chunkSize = chunkSize;
|
|
74
78
|
}
|
|
79
|
+
get target() {
|
|
80
|
+
return this.#manifestFile;
|
|
81
|
+
}
|
|
75
82
|
async write(collections) {
|
|
76
83
|
if (!this.#hasher) {
|
|
77
84
|
this.#hasher = await xxhash();
|
|
@@ -81,9 +88,10 @@ class ChunkedWriter {
|
|
|
81
88
|
for (const [collectionName, entries] of sortCollections(collections)) {
|
|
82
89
|
manifest[collectionName] = await this.#writeCollection(entries);
|
|
83
90
|
}
|
|
84
|
-
await writeFileAtomic(this.#manifestFile, JSON.stringify(manifest));
|
|
91
|
+
const didWrite = await writeFileAtomic(this.#manifestFile, JSON.stringify(manifest));
|
|
85
92
|
this.#writtenFiles.add(DATA_STORE_MANIFEST_FILE);
|
|
86
93
|
emptyDir(this.#dir, this.#writtenFiles);
|
|
94
|
+
return didWrite;
|
|
87
95
|
}
|
|
88
96
|
async #writeCollection(entries) {
|
|
89
97
|
const parts = [];
|
package/dist/content/index.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ export { createContentTypesGenerator } from './types-generator.js';
|
|
|
3
3
|
export { getContentPaths } from './utils.js';
|
|
4
4
|
export { astroContentAssetPropagationPlugin } from './vite-plugin-content-assets.js';
|
|
5
5
|
export { astroContentImportPlugin } from './vite-plugin-content-imports.js';
|
|
6
|
-
export { astroContentVirtualModPlugin } from './vite-plugin-content-virtual-mod.js';
|
|
6
|
+
export { astroContentVirtualModPlugin, attachDataStoreInvalidation, } from './vite-plugin-content-virtual-mod.js';
|
package/dist/content/index.js
CHANGED
|
@@ -3,12 +3,16 @@ import { createContentTypesGenerator } from "./types-generator.js";
|
|
|
3
3
|
import { getContentPaths } from "./utils.js";
|
|
4
4
|
import { astroContentAssetPropagationPlugin } from "./vite-plugin-content-assets.js";
|
|
5
5
|
import { astroContentImportPlugin } from "./vite-plugin-content-imports.js";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
astroContentVirtualModPlugin,
|
|
8
|
+
attachDataStoreInvalidation
|
|
9
|
+
} from "./vite-plugin-content-virtual-mod.js";
|
|
7
10
|
export {
|
|
8
11
|
astroContentAssetPropagationPlugin,
|
|
9
12
|
astroContentImportPlugin,
|
|
10
13
|
astroContentVirtualModPlugin,
|
|
11
14
|
attachContentServerListeners,
|
|
15
|
+
attachDataStoreInvalidation,
|
|
12
16
|
createContentTypesGenerator,
|
|
13
17
|
getContentPaths
|
|
14
18
|
};
|
|
@@ -6,6 +6,17 @@ import { type DataEntry, ImmutableDataStore } from './data-store.js';
|
|
|
6
6
|
*/
|
|
7
7
|
export declare class MutableDataStore extends ImmutableDataStore {
|
|
8
8
|
#private;
|
|
9
|
+
/**
|
|
10
|
+
* Registers a listener called with the file path whenever this store writes a
|
|
11
|
+
* file to disk (the data store itself, or the asset/module import files).
|
|
12
|
+
* Writes that are skipped because the data on disk is already identical do
|
|
13
|
+
* not notify. The dev server uses this to invalidate the content virtual
|
|
14
|
+
* modules deterministically, instead of relying on the file watcher to
|
|
15
|
+
* observe the write — on some platforms (notably Windows) the watcher can
|
|
16
|
+
* miss the atomic rename that commits it.
|
|
17
|
+
* Returns a function that removes the listener.
|
|
18
|
+
*/
|
|
19
|
+
onFileWritten(listener: (path: string) => void): () => void;
|
|
9
20
|
set(collectionName: string, key: string, value: unknown): void;
|
|
10
21
|
delete(collectionName: string, key: string): void;
|
|
11
22
|
clear(collectionName: string): void;
|
|
@@ -30,6 +30,32 @@ class MutableDataStore extends ImmutableDataStore {
|
|
|
30
30
|
#moduleImports = /* @__PURE__ */ new Map();
|
|
31
31
|
#writeInProgress = false;
|
|
32
32
|
#writeQueued = false;
|
|
33
|
+
#fileWrittenListeners = /* @__PURE__ */ new Set();
|
|
34
|
+
/**
|
|
35
|
+
* Registers a listener called with the file path whenever this store writes a
|
|
36
|
+
* file to disk (the data store itself, or the asset/module import files).
|
|
37
|
+
* Writes that are skipped because the data on disk is already identical do
|
|
38
|
+
* not notify. The dev server uses this to invalidate the content virtual
|
|
39
|
+
* modules deterministically, instead of relying on the file watcher to
|
|
40
|
+
* observe the write — on some platforms (notably Windows) the watcher can
|
|
41
|
+
* miss the atomic rename that commits it.
|
|
42
|
+
* Returns a function that removes the listener.
|
|
43
|
+
*/
|
|
44
|
+
onFileWritten(listener) {
|
|
45
|
+
this.#fileWrittenListeners.add(listener);
|
|
46
|
+
return () => {
|
|
47
|
+
this.#fileWrittenListeners.delete(listener);
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
#notifyFileWritten(path) {
|
|
51
|
+
if (this.#fileWrittenListeners.size === 0) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const normalized = path instanceof URL ? fileURLToPath(path) : path.toString();
|
|
55
|
+
for (const listener of this.#fileWrittenListeners) {
|
|
56
|
+
listener(normalized);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
33
59
|
set(collectionName, key, value) {
|
|
34
60
|
const collection = this._collections.get(collectionName) ?? /* @__PURE__ */ new Map();
|
|
35
61
|
collection.set(String(key), value);
|
|
@@ -275,6 +301,7 @@ ${lines.join(",\n")}]);
|
|
|
275
301
|
}
|
|
276
302
|
await fs.writeFile(tempFile, data);
|
|
277
303
|
await fs.rename(tempFile, filePath);
|
|
304
|
+
this.#notifyFileWritten(filePath);
|
|
278
305
|
} finally {
|
|
279
306
|
this.#writing.delete(fileKey);
|
|
280
307
|
if (this.#pending.has(fileKey)) {
|
|
@@ -415,7 +442,10 @@ ${lines.join(",\n")}]);
|
|
|
415
442
|
try {
|
|
416
443
|
this.#dirty = false;
|
|
417
444
|
this.#writeInProgress = true;
|
|
418
|
-
await this.#writer.write(this._collections);
|
|
445
|
+
const didWrite = await this.#writer.write(this._collections);
|
|
446
|
+
if (didWrite) {
|
|
447
|
+
this.#notifyFileWritten(this.#writer.target);
|
|
448
|
+
}
|
|
419
449
|
} catch (err) {
|
|
420
450
|
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: err });
|
|
421
451
|
} finally {
|
package/dist/content/runtime.js
CHANGED
|
@@ -349,7 +349,9 @@ async function updateImageReferencesInBody(html, fileName) {
|
|
|
349
349
|
return Object.entries({
|
|
350
350
|
...attributes,
|
|
351
351
|
src: image.src,
|
|
352
|
-
srcset
|
|
352
|
+
// An empty `srcset` is invalid HTML, so only emit it when there are
|
|
353
|
+
// actual candidates. This matches `vite-plugin-markdown/images.ts`.
|
|
354
|
+
...image.srcSet.values.length > 0 ? { srcset: image.srcSet.attribute } : {},
|
|
353
355
|
// This attribute is used by the toolbar audit
|
|
354
356
|
...import.meta.env.DEV ? { "data-image-component": "true" } : {}
|
|
355
357
|
}).filter(([, value]) => value != null).map(([key, value]) => value === "" ? `${key}=""` : `${key}="${escape(String(value))}"`).join(" ");
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import nodeFs from 'node:fs';
|
|
2
|
-
import { type Plugin } from 'vite';
|
|
2
|
+
import { type Plugin, type ViteDevServer } from 'vite';
|
|
3
3
|
import type { AstroSettings } from '../types/astro.js';
|
|
4
|
+
import type { MutableDataStore } from './mutable-data-store.js';
|
|
4
5
|
interface AstroContentVirtualModPluginParams {
|
|
5
6
|
settings: AstroSettings;
|
|
6
7
|
fs: typeof nodeFs;
|
|
7
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Invalidates the content virtual modules directly whenever the given store
|
|
11
|
+
* writes to disk. The watcher listeners in `configureServer` cover writes from
|
|
12
|
+
* other processes, but the watcher can miss the atomic rename that commits a
|
|
13
|
+
* write on some platforms (notably Windows, see #17335), leaving dev serving
|
|
14
|
+
* stale content until a restart. Subscribing to the store's own write
|
|
15
|
+
* notifications makes invalidation of this process's writes deterministic.
|
|
16
|
+
*/
|
|
17
|
+
export declare function attachDataStoreInvalidation(store: MutableDataStore, server: ViteDevServer, settings: AstroSettings): void;
|
|
8
18
|
export declare function astroContentVirtualModPlugin({ settings, fs, }: AstroContentVirtualModPluginParams): Plugin;
|
|
9
19
|
export {};
|
|
@@ -70,6 +70,35 @@ function invalidateDataStore(viteServer, { notifyClient = true } = {}) {
|
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
+
const directInvalidations = /* @__PURE__ */ new Map();
|
|
74
|
+
const DIRECT_INVALIDATION_ECHO_MS = 1e3;
|
|
75
|
+
function markDirectInvalidation(path) {
|
|
76
|
+
directInvalidations.set(path, Date.now());
|
|
77
|
+
}
|
|
78
|
+
function isDirectInvalidationEcho(path) {
|
|
79
|
+
const time = directInvalidations.get(path);
|
|
80
|
+
return time !== void 0 && Date.now() - time < DIRECT_INVALIDATION_ECHO_MS;
|
|
81
|
+
}
|
|
82
|
+
function getDevDataStoreFile(settings) {
|
|
83
|
+
if (getDataStoreChunkSize(settings) !== void 0) {
|
|
84
|
+
return new URL(DATA_STORE_MANIFEST_FILE, getDataStoreDir(settings, true));
|
|
85
|
+
}
|
|
86
|
+
return getDataStoreFile(settings, true);
|
|
87
|
+
}
|
|
88
|
+
function attachDataStoreInvalidation(store, server, settings) {
|
|
89
|
+
const dataStorePath = fileURLToPath(getDevDataStoreFile(settings));
|
|
90
|
+
const assetImportsPath = fileURLToPath(new URL(ASSET_IMPORTS_FILE, settings.dotAstroDir));
|
|
91
|
+
store.onFileWritten((path) => {
|
|
92
|
+
if (path === dataStorePath) {
|
|
93
|
+
markDirectInvalidation(dataStorePath);
|
|
94
|
+
invalidateDataStore(server);
|
|
95
|
+
invalidateAssetImports(server, assetImportsPath);
|
|
96
|
+
} else if (path === assetImportsPath) {
|
|
97
|
+
markDirectInvalidation(assetImportsPath);
|
|
98
|
+
invalidateAssetImports(server, assetImportsPath);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
73
102
|
function astroContentVirtualModPlugin({
|
|
74
103
|
settings,
|
|
75
104
|
fs
|
|
@@ -270,16 +299,19 @@ function astroContentVirtualModPlugin({
|
|
|
270
299
|
const dataStorePath = fileURLToPath(dataStoreFile);
|
|
271
300
|
const assetImportsPath = fileURLToPath(new URL(ASSET_IMPORTS_FILE, settings.dotAstroDir));
|
|
272
301
|
server.watcher.on("add", (addedPath) => {
|
|
273
|
-
if (addedPath === dataStorePath) {
|
|
302
|
+
if (addedPath === dataStorePath && !isDirectInvalidationEcho(dataStorePath)) {
|
|
274
303
|
invalidateDataStore(server);
|
|
275
304
|
invalidateAssetImports(server, assetImportsPath);
|
|
276
305
|
}
|
|
277
306
|
});
|
|
278
307
|
server.watcher.on("change", (changedPath) => {
|
|
279
308
|
if (changedPath === dataStorePath) {
|
|
309
|
+
if (isDirectInvalidationEcho(dataStorePath)) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
280
312
|
invalidateDataStore(server);
|
|
281
313
|
invalidateAssetImports(server, assetImportsPath);
|
|
282
|
-
} else if (changedPath === assetImportsPath) {
|
|
314
|
+
} else if (changedPath === assetImportsPath && !isDirectInvalidationEcho(assetImportsPath)) {
|
|
283
315
|
invalidateAssetImports(server, assetImportsPath);
|
|
284
316
|
}
|
|
285
317
|
});
|
|
@@ -314,5 +346,6 @@ async function generateContentEntryFile({
|
|
|
314
346
|
return virtualModContents;
|
|
315
347
|
}
|
|
316
348
|
export {
|
|
317
|
-
astroContentVirtualModPlugin
|
|
349
|
+
astroContentVirtualModPlugin,
|
|
350
|
+
attachDataStoreInvalidation
|
|
318
351
|
};
|
|
@@ -11,7 +11,7 @@ import { updateRouteTable } from "../../../routing/route-table.js";
|
|
|
11
11
|
import { DevFacadeApp } from "../../dev-facade.js";
|
|
12
12
|
let hmrWired = false;
|
|
13
13
|
const createApp = ({ streaming } = {}) => {
|
|
14
|
-
setLogger(manifest, createConsoleLogger(manifest.logLevel));
|
|
14
|
+
setLogger(manifest, createConsoleLogger({ level: manifest.logLevel }));
|
|
15
15
|
setEnvironment(manifest, createNonRunnableEnvironment());
|
|
16
16
|
const app = new DevFacadeApp(manifest, streaming);
|
|
17
17
|
app.setFetchHandler(fetchable);
|
|
@@ -22,7 +22,7 @@ const createApp = ({ streaming } = {}) => {
|
|
|
22
22
|
const { routes: newRoutes } = await import("virtual:astro:routes");
|
|
23
23
|
updateRouteTable(
|
|
24
24
|
manifest,
|
|
25
|
-
newRoutes.map((
|
|
25
|
+
newRoutes.map((route) => route.routeData)
|
|
26
26
|
);
|
|
27
27
|
} catch (e) {
|
|
28
28
|
getLogger(manifest).error("router", `Failed to update routes via HMR:
|
|
@@ -26,7 +26,6 @@ import { getRedirectLocationOrThrow } from "../redirects/index.js";
|
|
|
26
26
|
import { createRequest } from "../request.js";
|
|
27
27
|
import { redirectTemplate } from "../routing/3xx.js";
|
|
28
28
|
import { routeIsRedirect } from "../routing/helpers.js";
|
|
29
|
-
import { matchRoute } from "../routing/match.js";
|
|
30
29
|
import { getOutputFilename } from "../output-filename.js";
|
|
31
30
|
import { getOutFile, getOutFolder } from "./common.js";
|
|
32
31
|
import { createDefaultPrerenderer } from "./default-prerenderer.js";
|
|
@@ -102,7 +101,7 @@ ${colors.bgGreen(colors.black(` ${verb} static routes `))}`);
|
|
|
102
101
|
const pathsWithRoutes = await prerenderer.getStaticPaths();
|
|
103
102
|
const hasI18nDomains = ssr && options.settings.config.i18n?.domains && Object.keys(options.settings.config.i18n.domains).length > 0;
|
|
104
103
|
const { config } = options.settings;
|
|
105
|
-
const builtPaths = /* @__PURE__ */ new
|
|
104
|
+
const builtPaths = /* @__PURE__ */ new Map();
|
|
106
105
|
const filteredPaths = [];
|
|
107
106
|
const fallbackPaths = [];
|
|
108
107
|
for (const pathWithRoute of pathsWithRoutes) {
|
|
@@ -115,33 +114,28 @@ ${colors.bgGreen(colors.black(` ${verb} static routes `))}`);
|
|
|
115
114
|
}
|
|
116
115
|
const normalized = removeTrailingForwardSlash(pathname);
|
|
117
116
|
if (!builtPaths.has(normalized)) {
|
|
118
|
-
builtPaths.
|
|
117
|
+
builtPaths.set(normalized, route);
|
|
119
118
|
} else {
|
|
120
|
-
const
|
|
121
|
-
if (
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
throw new AstroError({
|
|
127
|
-
...AstroErrorData.PrerenderRouteConflict,
|
|
128
|
-
message: AstroErrorData.PrerenderRouteConflict.message(
|
|
129
|
-
matchedRoute.route,
|
|
130
|
-
route.route,
|
|
131
|
-
normalized
|
|
132
|
-
),
|
|
133
|
-
hint: AstroErrorData.PrerenderRouteConflict.hint(matchedRoute.route, route.route)
|
|
134
|
-
});
|
|
135
|
-
} else if (config.prerenderConflictBehavior === "warn") {
|
|
136
|
-
const msg = AstroErrorData.PrerenderRouteConflict.message(
|
|
137
|
-
matchedRoute.route,
|
|
119
|
+
const winningRoute = builtPaths.get(normalized);
|
|
120
|
+
if (config.prerenderConflictBehavior === "error") {
|
|
121
|
+
throw new AstroError({
|
|
122
|
+
...AstroErrorData.PrerenderRouteConflict,
|
|
123
|
+
message: AstroErrorData.PrerenderRouteConflict.message(
|
|
124
|
+
winningRoute.route,
|
|
138
125
|
route.route,
|
|
139
126
|
normalized
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
|
|
127
|
+
),
|
|
128
|
+
hint: AstroErrorData.PrerenderRouteConflict.hint(winningRoute.route, route.route)
|
|
129
|
+
});
|
|
130
|
+
} else if (config.prerenderConflictBehavior === "warn") {
|
|
131
|
+
const msg = AstroErrorData.PrerenderRouteConflict.message(
|
|
132
|
+
winningRoute.route,
|
|
133
|
+
route.route,
|
|
134
|
+
normalized
|
|
135
|
+
);
|
|
136
|
+
logger.warn("build", msg);
|
|
144
137
|
}
|
|
138
|
+
continue;
|
|
145
139
|
}
|
|
146
140
|
const paths = route.type === "fallback" ? fallbackPaths : filteredPaths;
|
|
147
141
|
paths.push(pathWithRoute);
|
|
@@ -31,7 +31,7 @@ import { makePageDataKey } from "./util.js";
|
|
|
31
31
|
import { cacheConfigToManifest } from "../../cache/utils.js";
|
|
32
32
|
import { sessionConfigToManifest } from "../../session/utils.js";
|
|
33
33
|
const MANIFEST_REPLACE = "@@ASTRO_MANIFEST_REPLACE@@";
|
|
34
|
-
const replaceExp = new RegExp(`['"]${MANIFEST_REPLACE}['"]`, "g");
|
|
34
|
+
const replaceExp = new RegExp(`['"\`]${MANIFEST_REPLACE}['"\`]`, "g");
|
|
35
35
|
async function manifestBuildPostHook(options, internals, {
|
|
36
36
|
chunks,
|
|
37
37
|
mutate
|
|
@@ -75,6 +75,9 @@ class AstroCache {
|
|
|
75
75
|
for (const [key, value] of headers) {
|
|
76
76
|
response.headers.set(key, value);
|
|
77
77
|
}
|
|
78
|
+
if (!response.headers.has("Cache-Control") && !response.headers.has("Expires") && (response.headers.has("Last-Modified") || response.headers.has("ETag"))) {
|
|
79
|
+
response.headers.set("Cache-Control", "no-cache");
|
|
80
|
+
}
|
|
78
81
|
}
|
|
79
82
|
/** @internal */
|
|
80
83
|
get [IS_ACTIVE]() {
|
package/dist/core/constants.js
CHANGED
package/dist/core/dev/dev.js
CHANGED
|
@@ -4,7 +4,7 @@ import colors from "piccolore";
|
|
|
4
4
|
import { gt, major, minor, patch } from "semver";
|
|
5
5
|
import { getDataStoreChunkSize, getDataStoreDir, getDataStoreFile } from "../../content/paths.js";
|
|
6
6
|
import { globalContentLayer } from "../../content/instance.js";
|
|
7
|
-
import { attachContentServerListeners } from "../../content/index.js";
|
|
7
|
+
import { attachContentServerListeners, attachDataStoreInvalidation } from "../../content/index.js";
|
|
8
8
|
import { MutableDataStore } from "../../content/mutable-data-store.js";
|
|
9
9
|
import { globalContentConfigObserver } from "../../content/utils.js";
|
|
10
10
|
import { telemetry } from "../../events/index.js";
|
|
@@ -26,7 +26,7 @@ async function dev(inlineConfig) {
|
|
|
26
26
|
await telemetry.record([]);
|
|
27
27
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
28
28
|
const logger = restart.container.logger;
|
|
29
|
-
const currentVersion = "7.2.
|
|
29
|
+
const currentVersion = "7.2.10";
|
|
30
30
|
const isPrerelease = currentVersion.includes("-");
|
|
31
31
|
if (!isPrerelease) {
|
|
32
32
|
try {
|
|
@@ -69,6 +69,8 @@ async function dev(inlineConfig) {
|
|
|
69
69
|
}
|
|
70
70
|
if (!store) {
|
|
71
71
|
logger.error("content", "Failed to create data store");
|
|
72
|
+
} else {
|
|
73
|
+
attachDataStoreInvalidation(store, restart.container.viteServer, restart.container.settings);
|
|
72
74
|
}
|
|
73
75
|
await attachContentServerListeners(restart.container);
|
|
74
76
|
const config = globalContentConfigObserver.get();
|
|
@@ -5,8 +5,8 @@ const RESOLVED_SERVER_ISLAND_MANIFEST = "\0" + SERVER_ISLAND_MANIFEST;
|
|
|
5
5
|
const serverIslandPlaceholderMap = "'$$server-islands-map$$'";
|
|
6
6
|
const serverIslandPlaceholderNameMap = "'$$server-islands-name-map$$'";
|
|
7
7
|
const SERVER_ISLAND_MAP_MARKER = "$$server-islands-map$$";
|
|
8
|
-
const serverIslandMapReplaceExp = /['"]\$\$server-islands-map\$\$['"]/g;
|
|
9
|
-
const serverIslandNameMapReplaceExp = /['"]\$\$server-islands-name-map\$\$['"]/g;
|
|
8
|
+
const serverIslandMapReplaceExp = /['"`]\$\$server-islands-map\$\$['"`]/g;
|
|
9
|
+
const serverIslandNameMapReplaceExp = /['"`]\$\$server-islands-name-map\$\$['"`]/g;
|
|
10
10
|
function vitePluginServerIslands({
|
|
11
11
|
settings,
|
|
12
12
|
serverIslandsState
|
package/dist/core/util.d.ts
CHANGED
|
@@ -23,15 +23,6 @@ export declare function wrapId(id: string): string;
|
|
|
23
23
|
export declare function resolvePages(config: AstroConfig): URL;
|
|
24
24
|
export declare function isPage(file: URL, settings: AstroSettings): boolean;
|
|
25
25
|
export declare function isEndpoint(file: URL, settings: AstroSettings): boolean;
|
|
26
|
-
export declare function resolveJsToTs(filePath: string): string;
|
|
27
|
-
/**
|
|
28
|
-
* Resolve a path that doesn't name a file on disk (e.g. produced by an
|
|
29
|
-
* extensionless import like `import { Counter } from './Counter'`) to the file
|
|
30
|
-
* Vite would load, by probing Vite's default extension order and directory
|
|
31
|
-
* `index` files. Returns the path unchanged when it already exists as a file
|
|
32
|
-
* or when no candidate is found.
|
|
33
|
-
*/
|
|
34
|
-
export declare function resolveExtensionlessPath(filePath: string): string;
|
|
35
26
|
/**
|
|
36
27
|
* Set a default NODE_ENV so Vite doesn't set an incorrect default when loading the Astro config
|
|
37
28
|
*/
|
package/dist/core/util.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
1
|
import { fileURLToPath } from "node:url";
|
|
3
2
|
import { hasSpecialQueries } from "../vite-plugin-utils/index.js";
|
|
4
3
|
import { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from "./constants.js";
|
|
@@ -85,37 +84,6 @@ function isEndpoint(file, settings) {
|
|
|
85
84
|
if (!isPublicRoute(file, settings.config)) return false;
|
|
86
85
|
return !endsWithPageExt(file, settings) && !file.toString().includes("?astro");
|
|
87
86
|
}
|
|
88
|
-
function resolveJsToTs(filePath) {
|
|
89
|
-
if (filePath.endsWith(".jsx") && !fs.existsSync(filePath)) {
|
|
90
|
-
const tryPath = filePath.slice(0, -4) + ".tsx";
|
|
91
|
-
if (fs.existsSync(tryPath)) {
|
|
92
|
-
return tryPath;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return filePath;
|
|
96
|
-
}
|
|
97
|
-
const VITE_DEFAULT_RESOLVE_EXTENSIONS = [".mjs", ".js", ".mts", ".ts", ".jsx", ".tsx", ".json"];
|
|
98
|
-
function resolveExtensionlessPath(filePath) {
|
|
99
|
-
const stat = fs.statSync(filePath, { throwIfNoEntry: false });
|
|
100
|
-
if (stat?.isFile()) {
|
|
101
|
-
return filePath;
|
|
102
|
-
}
|
|
103
|
-
for (const ext of VITE_DEFAULT_RESOLVE_EXTENSIONS) {
|
|
104
|
-
const tryPath = filePath + ext;
|
|
105
|
-
if (fs.existsSync(tryPath)) {
|
|
106
|
-
return tryPath;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
if (stat?.isDirectory()) {
|
|
110
|
-
for (const ext of VITE_DEFAULT_RESOLVE_EXTENSIONS) {
|
|
111
|
-
const tryPath = `${filePath}/index${ext}`;
|
|
112
|
-
if (fs.existsSync(tryPath)) {
|
|
113
|
-
return tryPath;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return filePath;
|
|
118
|
-
}
|
|
119
87
|
function ensureProcessNodeEnv(defaultNodeEnv) {
|
|
120
88
|
if (!process.env.NODE_ENV) {
|
|
121
89
|
process.env.NODE_ENV = defaultNodeEnv;
|
|
@@ -128,8 +96,6 @@ export {
|
|
|
128
96
|
isMarkdownFile,
|
|
129
97
|
isPage,
|
|
130
98
|
parseNpmName,
|
|
131
|
-
resolveExtensionlessPath,
|
|
132
|
-
resolveJsToTs,
|
|
133
99
|
resolvePages,
|
|
134
100
|
unwrapId,
|
|
135
101
|
viteID,
|
package/dist/core/viteUtils.d.ts
CHANGED
|
@@ -1,21 +1,9 @@
|
|
|
1
1
|
import type { ModuleLoader } from './module-loader/index.js';
|
|
2
|
+
export { resolvePath } from '@astrojs/internal-helpers/mdx';
|
|
2
3
|
/**
|
|
3
4
|
* Re-implementation of Vite's normalizePath that can be used without Vite
|
|
4
5
|
*/
|
|
5
6
|
export declare function normalizePath(id: string): string;
|
|
6
|
-
/**
|
|
7
|
-
* Resolve island component specifiers to stable paths for hydration metadata.
|
|
8
|
-
*
|
|
9
|
-
* Examples:
|
|
10
|
-
* - `./components/Button.jsx` from `/app/src/pages/index.astro`
|
|
11
|
-
* -> `/app/src/pages/components/Button.tsx` (when `.tsx` exists)
|
|
12
|
-
* - `../components/Counter` from `/app/src/pages/index.astro`
|
|
13
|
-
* -> `/app/src/components/Counter.tsx` (extensionless imports probe Vite's
|
|
14
|
-
* default extension order, then directory `index` files)
|
|
15
|
-
* - `#components/react/Counter.tsx`
|
|
16
|
-
* -> `/app/src/components/react/Counter.tsx` via package `imports`
|
|
17
|
-
*/
|
|
18
|
-
export declare function resolvePath(specifier: string, importer: string): string;
|
|
19
7
|
export declare function rootRelativePath(root: URL, idOrUrl: URL | string, shouldPrependForwardSlash?: boolean): string;
|
|
20
8
|
/**
|
|
21
9
|
* Simulate Vite's resolve and import analysis so we can import the id as an URL
|
package/dist/core/viteUtils.js
CHANGED
|
@@ -1,42 +1,12 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
1
|
import path from "node:path";
|
|
3
|
-
import { fileURLToPath
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
4
3
|
import { prependForwardSlash, slash } from "../core/path.js";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
resolveJsToTs,
|
|
8
|
-
unwrapId,
|
|
9
|
-
VALID_ID_PREFIX,
|
|
10
|
-
viteID
|
|
11
|
-
} from "./util.js";
|
|
4
|
+
import { unwrapId, VALID_ID_PREFIX, viteID } from "./util.js";
|
|
5
|
+
import { resolvePath } from "@astrojs/internal-helpers/mdx";
|
|
12
6
|
const isWindows = typeof process !== "undefined" && process.platform === "win32";
|
|
13
7
|
function normalizePath(id) {
|
|
14
8
|
return path.posix.normalize(isWindows ? slash(id) : id);
|
|
15
9
|
}
|
|
16
|
-
function resolvePath(specifier, importer) {
|
|
17
|
-
if (specifier.startsWith(".")) {
|
|
18
|
-
const absoluteSpecifier = path.resolve(path.dirname(importer), specifier);
|
|
19
|
-
return resolveExtensionlessPath(resolveJsToTs(normalizePath(absoluteSpecifier)));
|
|
20
|
-
} else if (specifier.startsWith("#")) {
|
|
21
|
-
try {
|
|
22
|
-
const resolved = createRequire(pathToFileURL(importer)).resolve(specifier);
|
|
23
|
-
return resolveJsToTs(normalizePath(resolved));
|
|
24
|
-
} catch {
|
|
25
|
-
try {
|
|
26
|
-
const importerURL = pathToFileURL(importer).toString();
|
|
27
|
-
const resolved = import.meta.resolve(specifier, importerURL);
|
|
28
|
-
const resolvedUrl = new URL(resolved);
|
|
29
|
-
if (resolvedUrl.protocol === "file:") {
|
|
30
|
-
return resolveJsToTs(normalizePath(fileURLToPath(resolvedUrl)));
|
|
31
|
-
}
|
|
32
|
-
} catch {
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return specifier;
|
|
36
|
-
} else {
|
|
37
|
-
return specifier;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
10
|
function rootRelativePath(root, idOrUrl, shouldPrependForwardSlash = true) {
|
|
41
11
|
let id;
|
|
42
12
|
if (typeof idOrUrl !== "string") {
|
|
@@ -47,7 +47,7 @@ async function createAstroServerApp(controller, settings, loader, logger) {
|
|
|
47
47
|
const { routes: newRoutes } = await import("virtual:astro:routes");
|
|
48
48
|
updateRouteTable(
|
|
49
49
|
manifest,
|
|
50
|
-
newRoutes.map((
|
|
50
|
+
newRoutes.map((route) => route.routeData)
|
|
51
51
|
);
|
|
52
52
|
actualLogger.debug("router", "Routes updated via HMR");
|
|
53
53
|
} catch (e) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro",
|
|
3
|
-
"version": "7.2.
|
|
3
|
+
"version": "7.2.10",
|
|
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",
|
|
@@ -153,15 +153,15 @@
|
|
|
153
153
|
"xxhash-wasm": "^1.1.0",
|
|
154
154
|
"yargs-parser": "^22.0.0",
|
|
155
155
|
"zod": "^4.3.6",
|
|
156
|
-
"@astrojs/
|
|
157
|
-
"@astrojs/
|
|
156
|
+
"@astrojs/internal-helpers": "0.11.0",
|
|
157
|
+
"@astrojs/markdown-satteri": "0.4.0",
|
|
158
158
|
"@astrojs/telemetry": "3.3.3"
|
|
159
159
|
},
|
|
160
160
|
"optionalDependencies": {
|
|
161
161
|
"sharp": "^0.35.4"
|
|
162
162
|
},
|
|
163
163
|
"peerDependencies": {
|
|
164
|
-
"@astrojs/markdown-remark": "7.
|
|
164
|
+
"@astrojs/markdown-remark": "^7.3.0"
|
|
165
165
|
},
|
|
166
166
|
"peerDependenciesMeta": {
|
|
167
167
|
"@astrojs/markdown-remark": {
|
|
@@ -193,8 +193,8 @@
|
|
|
193
193
|
"typescript": "^6.0.3",
|
|
194
194
|
"undici": "^7.22.0",
|
|
195
195
|
"vitest": "^4.1.0",
|
|
196
|
-
"@astrojs/markdown-remark": "7.2.4",
|
|
197
196
|
"@astrojs/check": "0.9.10",
|
|
197
|
+
"@astrojs/markdown-remark": "7.3.0",
|
|
198
198
|
"astro-scripts": "0.0.14"
|
|
199
199
|
},
|
|
200
200
|
"engines": {
|