astro 7.2.2 → 7.2.3

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 (151) hide show
  1. package/dist/actions/handler.d.ts +6 -12
  2. package/dist/actions/handler.js +30 -40
  3. package/dist/actions/load.d.ts +12 -0
  4. package/dist/actions/load.js +55 -0
  5. package/dist/actions/runtime/entrypoints/server.js +5 -4
  6. package/dist/actions/runtime/server.js +8 -6
  7. package/dist/assets/fonts/providers/index.d.ts +1 -1
  8. package/dist/assets/fonts/providers/index.js +2 -12
  9. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  10. package/dist/container/environment.d.ts +20 -0
  11. package/dist/container/environment.js +106 -0
  12. package/dist/container/index.js +65 -32
  13. package/dist/content/content-layer.js +3 -3
  14. package/dist/content/data-store-writer.d.ts +7 -10
  15. package/dist/content/data-store-writer.js +62 -27
  16. package/dist/content/data-store.d.ts +20 -3
  17. package/dist/content/data-store.js +28 -7
  18. package/dist/content/mutable-data-store.js +15 -10
  19. package/dist/content/runtime.d.ts +3 -2
  20. package/dist/content/runtime.js +43 -26
  21. package/dist/core/app/app.d.ts +0 -2
  22. package/dist/core/app/app.js +0 -7
  23. package/dist/core/app/base.d.ts +32 -20
  24. package/dist/core/app/base.js +76 -66
  25. package/dist/core/app/dev-facade.d.ts +27 -0
  26. package/dist/core/app/dev-facade.js +51 -0
  27. package/dist/core/app/entrypoints/index.d.ts +0 -1
  28. package/dist/core/app/entrypoints/index.js +0 -2
  29. package/dist/core/app/entrypoints/virtual/dev.js +24 -19
  30. package/dist/core/app/node.js +13 -14
  31. package/dist/core/app/prepare-response.d.ts +1 -1
  32. package/dist/core/app/validate-headers.js +7 -3
  33. package/dist/core/build/app.d.ts +31 -6
  34. package/dist/core/build/app.js +31 -13
  35. package/dist/core/build/environment.d.ts +25 -0
  36. package/dist/core/build/environment.js +157 -0
  37. package/dist/core/cache/handler.d.ts +13 -7
  38. package/dist/core/cache/handler.js +55 -51
  39. package/dist/core/cache/provider.d.ts +4 -0
  40. package/dist/core/cache/provider.js +15 -0
  41. package/dist/core/constants.d.ts +0 -11
  42. package/dist/core/constants.js +1 -5
  43. package/dist/core/dev/dev.js +1 -1
  44. package/dist/core/environment/dev-nonrunnable.d.ts +6 -0
  45. package/dist/core/environment/dev-nonrunnable.js +170 -0
  46. package/dist/core/environment/index.d.ts +90 -0
  47. package/dist/core/environment/index.js +12 -0
  48. package/dist/core/environment/production.d.ts +6 -0
  49. package/dist/core/environment/production.js +117 -0
  50. package/dist/core/errors/build-handler.d.ts +5 -10
  51. package/dist/core/errors/build-handler.js +11 -17
  52. package/dist/core/errors/default-handler.d.ts +4 -9
  53. package/dist/core/errors/default-handler.js +92 -107
  54. package/dist/core/errors/dev-handler.d.ts +7 -11
  55. package/dist/core/errors/dev-handler.js +71 -69
  56. package/dist/core/errors/errors-data.d.ts +18 -0
  57. package/dist/core/errors/errors-data.js +7 -0
  58. package/dist/core/errors/handler.d.ts +22 -3
  59. package/dist/core/errors/handler.js +25 -0
  60. package/dist/core/fetch/default-handler.d.ts +15 -8
  61. package/dist/core/fetch/default-handler.js +12 -34
  62. package/dist/core/fetch/features.d.ts +23 -0
  63. package/dist/core/fetch/features.js +27 -0
  64. package/dist/core/fetch/fetch-state.d.ts +52 -7
  65. package/dist/core/fetch/fetch-state.js +92 -81
  66. package/dist/core/fetch/index.d.ts +9 -2
  67. package/dist/core/fetch/index.js +18 -79
  68. package/dist/core/fetch/vite-plugin.js +2 -1
  69. package/dist/core/i18n/handler.d.ts +28 -13
  70. package/dist/core/i18n/handler.js +100 -100
  71. package/dist/core/logger/manifest-logger.d.ts +31 -0
  72. package/dist/core/logger/manifest-logger.js +37 -0
  73. package/dist/core/manifest/ambient-source.d.ts +2 -0
  74. package/dist/core/manifest/ambient-source.js +4 -0
  75. package/dist/core/manifest/ambient.d.ts +16 -0
  76. package/dist/core/manifest/ambient.js +22 -0
  77. package/dist/core/manifest/derived.d.ts +3 -0
  78. package/dist/core/manifest/derived.js +10 -0
  79. package/dist/core/manifest/memo.d.ts +31 -0
  80. package/dist/core/manifest/memo.js +47 -0
  81. package/dist/core/messages/runtime.js +1 -1
  82. package/dist/core/middleware/astro-middleware.d.ts +25 -35
  83. package/dist/core/middleware/astro-middleware.js +61 -81
  84. package/dist/core/middleware/load.d.ts +19 -0
  85. package/dist/core/middleware/load.js +36 -0
  86. package/dist/core/middleware/sequence.js +15 -7
  87. package/dist/core/pages/handler.d.ts +18 -25
  88. package/dist/core/pages/handler.js +68 -84
  89. package/dist/core/redirects/render.js +3 -8
  90. package/dist/core/render/index.d.ts +0 -1
  91. package/dist/core/render/index.js +0 -2
  92. package/dist/core/render/route-cache.d.ts +6 -1
  93. package/dist/core/render/route-cache.js +11 -1
  94. package/dist/core/rewrites/handler.d.ts +4 -6
  95. package/dist/core/rewrites/handler.js +19 -20
  96. package/dist/core/routing/default.d.ts +2 -0
  97. package/dist/core/routing/default.js +7 -1
  98. package/dist/core/routing/dev.d.ts +1 -3
  99. package/dist/core/routing/dev.js +12 -5
  100. package/dist/core/routing/handler.d.ts +6 -16
  101. package/dist/core/routing/handler.js +126 -164
  102. package/dist/core/routing/helpers.d.ts +7 -1
  103. package/dist/core/routing/helpers.js +21 -0
  104. package/dist/core/routing/match-request.d.ts +10 -0
  105. package/dist/core/routing/match-request.js +57 -0
  106. package/dist/core/routing/route-table.d.ts +34 -0
  107. package/dist/core/routing/route-table.js +41 -0
  108. package/dist/core/routing/trailing-slash-handler.d.ts +4 -14
  109. package/dist/core/routing/trailing-slash-handler.js +39 -50
  110. package/dist/core/server-islands/mappings.d.ts +6 -0
  111. package/dist/core/server-islands/mappings.js +12 -0
  112. package/dist/core/session/driver.d.ts +4 -0
  113. package/dist/core/session/driver.js +14 -0
  114. package/dist/core/session/handler.d.ts +1 -1
  115. package/dist/core/session/handler.js +8 -8
  116. package/dist/core/session/provider-disabled.js +2 -2
  117. package/dist/entrypoints/prerender.js +5 -1
  118. package/dist/i18n/middleware.d.ts +4 -4
  119. package/dist/i18n/middleware.js +3 -3
  120. package/dist/manifest/serialized.d.ts +1 -0
  121. package/dist/manifest/serialized.js +9 -2
  122. package/dist/runtime/prerender/static-paths.d.ts +14 -2
  123. package/dist/runtime/prerender/static-paths.js +4 -3
  124. package/dist/types/public/config.d.ts +433 -241
  125. package/dist/vite-plugin-app/createAstroServerApp.js +22 -18
  126. package/dist/vite-plugin-app/environment.d.ts +18 -0
  127. package/dist/vite-plugin-app/environment.js +210 -0
  128. package/dist/vite-plugin-app/handle-request.d.ts +30 -0
  129. package/dist/vite-plugin-app/handle-request.js +129 -0
  130. package/dist/vite-plugin-app/index.d.ts +1 -1
  131. package/dist/vite-plugin-app/index.js +1 -1
  132. package/package.json +14 -7
  133. package/src/core/README.md +37 -0
  134. package/src/core/manifest/ambient-source.ts +9 -0
  135. package/src/types/README.md +5 -0
  136. package/dist/container/pipeline.d.ts +0 -14
  137. package/dist/container/pipeline.js +0 -78
  138. package/dist/core/app/dev/app.d.ts +0 -31
  139. package/dist/core/app/dev/app.js +0 -80
  140. package/dist/core/app/dev/pipeline.d.ts +0 -17
  141. package/dist/core/app/dev/pipeline.js +0 -133
  142. package/dist/core/app/pipeline.d.ts +0 -14
  143. package/dist/core/app/pipeline.js +0 -123
  144. package/dist/core/base-pipeline.d.ts +0 -183
  145. package/dist/core/base-pipeline.js +0 -293
  146. package/dist/core/build/pipeline.d.ts +0 -38
  147. package/dist/core/build/pipeline.js +0 -202
  148. package/dist/vite-plugin-app/app.d.ts +0 -62
  149. package/dist/vite-plugin-app/app.js +0 -237
  150. package/dist/vite-plugin-app/pipeline.d.ts +0 -25
  151. package/dist/vite-plugin-app/pipeline.js +0 -189
@@ -15,23 +15,31 @@ function serializeDataStore(collections) {
15
15
  return devalue.stringify(sortCollections(collections));
16
16
  }
17
17
  const ENCODER = new TextEncoder();
18
+ function getChunkEnd(str, startIndex, maxBytes) {
19
+ let index = startIndex;
20
+ let bytes = 0;
21
+ while (index < str.length) {
22
+ const codePoint = str.codePointAt(index);
23
+ const charLength = codePoint > 65535 ? 2 : 1;
24
+ const charBytes = ENCODER.encode(str.slice(index, index + charLength)).length;
25
+ if (bytes + charBytes > maxBytes && index > startIndex) {
26
+ break;
27
+ }
28
+ index += charLength;
29
+ bytes += charBytes;
30
+ if (bytes >= maxBytes) {
31
+ break;
32
+ }
33
+ }
34
+ return { endIndex: index, bytes };
35
+ }
18
36
  function chunkString(str, maxBytes) {
19
37
  const chunks = [];
20
38
  let startIndex = 0;
21
- let index = 0;
22
- let currentBytes = 0;
23
- for (const char of str) {
24
- const charBytes = ENCODER.encode(char).length;
25
- if (currentBytes + charBytes > maxBytes && index > startIndex) {
26
- chunks.push(str.slice(startIndex, index));
27
- startIndex = index;
28
- currentBytes = 0;
29
- }
30
- index += char.length;
31
- currentBytes += charBytes;
32
- }
33
- if (startIndex < str.length) {
34
- chunks.push(str.slice(startIndex));
39
+ while (startIndex < str.length) {
40
+ const { endIndex } = getChunkEnd(str, startIndex, maxBytes);
41
+ chunks.push(str.slice(startIndex, endIndex));
42
+ startIndex = endIndex;
35
43
  }
36
44
  return chunks;
37
45
  }
@@ -58,6 +66,7 @@ class ChunkedWriter {
58
66
  #manifestFile;
59
67
  #chunkSize;
60
68
  #hasher;
69
+ #writtenFiles = /* @__PURE__ */ new Set();
61
70
  constructor(dir, chunkSize) {
62
71
  this.#dir = dir;
63
72
  this.#manifestFile = new URL(`./${DATA_STORE_MANIFEST_FILE}`, dir);
@@ -67,23 +76,49 @@ class ChunkedWriter {
67
76
  if (!this.#hasher) {
68
77
  this.#hasher = await xxhash();
69
78
  }
70
- const { h64ToString } = this.#hasher;
71
- const writtenFiles = /* @__PURE__ */ new Set();
79
+ this.#writtenFiles = /* @__PURE__ */ new Set();
72
80
  const manifest = {};
73
81
  for (const [collectionName, entries] of sortCollections(collections)) {
74
- const stringified = devalue.stringify(entries);
75
- const parts = [];
76
- for (const part of chunkString(stringified, this.#chunkSize)) {
77
- const fileName = `${h64ToString(part)}.txt`;
78
- await writeFileAtomic(new URL(`./${fileName}`, this.#dir), part);
79
- parts.push(fileName);
80
- writtenFiles.add(fileName);
81
- }
82
- manifest[collectionName] = parts;
82
+ manifest[collectionName] = await this.#writeCollection(entries);
83
83
  }
84
84
  await writeFileAtomic(this.#manifestFile, JSON.stringify(manifest));
85
- writtenFiles.add(DATA_STORE_MANIFEST_FILE);
86
- emptyDir(this.#dir, writtenFiles);
85
+ this.#writtenFiles.add(DATA_STORE_MANIFEST_FILE);
86
+ emptyDir(this.#dir, this.#writtenFiles);
87
+ }
88
+ async #writeCollection(entries) {
89
+ const parts = [];
90
+ let chunk = "";
91
+ let chunkBytes = 0;
92
+ const writeChunk = async () => {
93
+ const fileName = `${this.#hasher.h64ToString(chunk)}.txt`;
94
+ await writeFileAtomic(new URL(`./${fileName}`, this.#dir), chunk);
95
+ parts.push(fileName);
96
+ this.#writtenFiles.add(fileName);
97
+ chunk = "";
98
+ chunkBytes = 0;
99
+ };
100
+ for (const [id, entry] of entries) {
101
+ const serialized = `${devalue.stringify([id, entry])}
102
+ `;
103
+ let startIndex = 0;
104
+ while (startIndex < serialized.length) {
105
+ const { endIndex, bytes } = getChunkEnd(
106
+ serialized,
107
+ startIndex,
108
+ this.#chunkSize - chunkBytes
109
+ );
110
+ chunk += serialized.slice(startIndex, endIndex);
111
+ chunkBytes += bytes;
112
+ startIndex = endIndex;
113
+ if (chunkBytes >= this.#chunkSize) {
114
+ await writeChunk();
115
+ }
116
+ }
117
+ }
118
+ if (chunk) {
119
+ await writeChunk();
120
+ }
121
+ return parts;
87
122
  }
88
123
  }
89
124
  export {
@@ -31,6 +31,24 @@ export interface DataEntry<TData extends Record<string, unknown> = Record<string
31
31
  */
32
32
  deferredRender?: boolean;
33
33
  assetImports?: Array<string>;
34
+ /**
35
+ * Locations of image fields within `data`, recorded when the entry is stored.
36
+ * Each path is the sequence of keys from `data` to a field that holds an image
37
+ * src string. At read time these fields are resolved to `ImageMetadata` without
38
+ * traversing or cloning the rest of `data`, so sibling values that devalue can
39
+ * serialize but `structuredClone` cannot (e.g. class instances) are left
40
+ * untouched.
41
+ */
42
+ imageImports?: (string | number)[][];
43
+ }
44
+ /**
45
+ * Rebuilds a collection from ordered parts containing newline-delimited
46
+ * `devalue.stringify([id, entry])` records.
47
+ */
48
+ export declare class ChunkedCollectionParser {
49
+ #private;
50
+ add(part: string): void;
51
+ finish(): Map<string, any>;
34
52
  }
35
53
  /**
36
54
  * A read-only data store for content collections. This is used to retrieve data from the content layer at runtime.
@@ -52,9 +70,8 @@ export declare class ImmutableDataStore {
52
70
  *
53
71
  * Each collection maps to a list of parts. A part is either a raw string
54
72
  * (when the store is loaded from disk) or an ESM namespace from a virtual
55
- * chunk import (`{ default: string }`, when emitted at runtime). A collection's
56
- * parts are concatenated back into the exact
57
- * serialized string, then parsed with devalue. This is the inverse of
73
+ * chunk import (`{ default: string }`, when emitted at runtime). Each part
74
+ * contains independently serialized entry records. This is the inverse of
58
75
  * {@link import('./data-store-writer.js').ChunkedWriter} and stays free of
59
76
  * Node built-ins so it can run at runtime.
60
77
  */
@@ -1,5 +1,27 @@
1
1
  import * as devalue from "devalue";
2
2
  import { InMemorySource } from "./data-store-source.js";
3
+ class ChunkedCollectionParser {
4
+ #entries = /* @__PURE__ */ new Map();
5
+ #remainder = "";
6
+ add(part) {
7
+ const content = this.#remainder + part;
8
+ const records = content.split("\n");
9
+ this.#remainder = records.pop();
10
+ for (const record of records) {
11
+ const parsed = devalue.parse(record);
12
+ if (!Array.isArray(parsed) || parsed.length !== 2 || typeof parsed[0] !== "string") {
13
+ throw new Error("Invalid chunked data store entry");
14
+ }
15
+ this.#entries.set(parsed[0], parsed[1]);
16
+ }
17
+ }
18
+ finish() {
19
+ if (this.#remainder) {
20
+ throw new Error("Invalid chunked data store entry");
21
+ }
22
+ return this.#entries;
23
+ }
24
+ }
3
25
  class ImmutableDataStore {
4
26
  _collections = /* @__PURE__ */ new Map();
5
27
  constructor() {
@@ -39,21 +61,19 @@ class ImmutableDataStore {
39
61
  *
40
62
  * Each collection maps to a list of parts. A part is either a raw string
41
63
  * (when the store is loaded from disk) or an ESM namespace from a virtual
42
- * chunk import (`{ default: string }`, when emitted at runtime). A collection's
43
- * parts are concatenated back into the exact
44
- * serialized string, then parsed with devalue. This is the inverse of
64
+ * chunk import (`{ default: string }`, when emitted at runtime). Each part
65
+ * contains independently serialized entry records. This is the inverse of
45
66
  * {@link import('./data-store-writer.js').ChunkedWriter} and stays free of
46
67
  * Node built-ins so it can run at runtime.
47
68
  */
48
69
  static manifestToMap(manifest) {
49
70
  const collections = /* @__PURE__ */ new Map();
50
71
  for (const [collectionName, parts] of Object.entries(manifest)) {
51
- let stringified = "";
72
+ const parser = new ChunkedCollectionParser();
52
73
  for (const part of parts) {
53
- stringified += typeof part === "string" ? part : part.default;
74
+ parser.add(typeof part === "string" ? part : part.default);
54
75
  }
55
- const entries = devalue.parse(stringified);
56
- collections.set(collectionName, entries);
76
+ collections.set(collectionName, parser.finish());
57
77
  }
58
78
  return collections;
59
79
  }
@@ -100,6 +120,7 @@ function dataStoreSingleton() {
100
120
  }
101
121
  const globalDataStore = dataStoreSingleton();
102
122
  export {
123
+ ChunkedCollectionParser,
103
124
  ImmutableDataStore,
104
125
  globalDataStore
105
126
  };
@@ -10,7 +10,7 @@ import {
10
10
  FileWriter,
11
11
  serializeDataStore
12
12
  } from "./data-store-writer.js";
13
- import { ImmutableDataStore } from "./data-store.js";
13
+ import { ChunkedCollectionParser, ImmutableDataStore } from "./data-store.js";
14
14
  import { contentModuleToId } from "./utils.js";
15
15
  const SAVE_DEBOUNCE_MS = 500;
16
16
  const MAX_DEPTH = 10;
@@ -276,10 +276,13 @@ ${lines.join(",\n")}]);
276
276
  }
277
277
  }
278
278
  const foundAssets = new Set(assetImports);
279
- forEach(data, (_, val) => {
279
+ const imageImports = [];
280
+ forEach(data, function(ctx, val) {
280
281
  if (typeof val === "string" && val.startsWith(IMAGE_IMPORT_PREFIX)) {
281
282
  const src = val.replace(IMAGE_IMPORT_PREFIX, "");
282
283
  foundAssets.add(src);
284
+ imageImports.push(ctx.path.map((segment) => segment));
285
+ ctx.update(src);
283
286
  }
284
287
  });
285
288
  const entry = {
@@ -299,6 +302,9 @@ ${lines.join(",\n")}]);
299
302
  entry.assetImports = Array.from(foundAssets);
300
303
  this.addAssetImports(entry.assetImports, filePath);
301
304
  }
305
+ if (imageImports.length) {
306
+ entry.imageImports = imageImports;
307
+ }
302
308
  if (digest) {
303
309
  entry.digest = digest;
304
310
  }
@@ -424,16 +430,15 @@ ${lines.join(",\n")}]);
424
430
  try {
425
431
  const manifestData = await fs.readFile(manifestFile, "utf-8");
426
432
  const manifest = JSON.parse(manifestData);
427
- const expanded = {};
433
+ const collections = /* @__PURE__ */ new Map();
428
434
  for (const collectionName in manifest) {
429
- expanded[collectionName] = await Promise.all(
430
- manifest[collectionName].map(
431
- (fileName) => fs.readFile(new URL(`./${fileName}`, dirPath), "utf-8")
432
- )
433
- );
435
+ const parser = new ChunkedCollectionParser();
436
+ for (const fileName of manifest[collectionName]) {
437
+ parser.add(await fs.readFile(new URL(`./${fileName}`, dirPath), "utf-8"));
438
+ }
439
+ collections.set(collectionName, parser.finish());
434
440
  }
435
- const map = ImmutableDataStore.manifestToMap(expanded);
436
- const store2 = await MutableDataStore.fromMap(map);
441
+ const store2 = await MutableDataStore.fromMap(collections);
437
442
  store2.#writer = new ChunkedWriter(dirPath, chunkSize);
438
443
  return store2;
439
444
  } catch (err) {
@@ -4,7 +4,7 @@ import type * as zCore from 'zod/v4/core';
4
4
  import type { ImageMetadata } from '../assets/types.js';
5
5
  import { type AstroComponentFactory } from '../runtime/server/index.js';
6
6
  import type { LiveDataCollectionResult, LiveDataEntryResult } from '../types/public/content.js';
7
- import { type LIVE_CONTENT_TYPE } from './consts.js';
7
+ import type { LIVE_CONTENT_TYPE } from './consts.js';
8
8
  import { type DataEntry } from './data-store.js';
9
9
  import { LiveCollectionCacheHintError, LiveCollectionError, LiveCollectionValidationError, LiveEntryNotFoundError } from './loaders/errors.js';
10
10
  import type { LiveLoader } from './loaders/types.js';
@@ -26,6 +26,7 @@ export declare function createGetCollection({ liveCollections, }: {
26
26
  rendered?: import("./data-store.js").RenderedContent;
27
27
  deferredRender?: boolean;
28
28
  assetImports?: Array<string>;
29
+ imageImports?: (string | number)[][];
29
30
  }[]>;
30
31
  type ContentEntryResult = {
31
32
  id: string;
@@ -70,7 +71,7 @@ type RenderResult = {
70
71
  headings: MarkdownHeading[];
71
72
  remarkPluginFrontmatter: Record<string, any>;
72
73
  };
73
- export declare function updateImageReferencesInData<T extends Record<string, unknown>>(data: T, fileName?: string, imageAssetMap?: Map<string, ImageMetadata>): T;
74
+ export declare function updateImageReferencesInData<T extends Record<string, unknown>>(data: T, fileName?: string, imageAssetMap?: Map<string, ImageMetadata>, imageImports?: (string | number)[][]): T;
74
75
  export declare function resolveEntryData<T extends Record<string, unknown>>(entry: DataEntry<T>, imageAssetMap?: Map<string, ImageMetadata>): T;
75
76
  export declare function renderEntry(entry: DataEntry): Promise<RenderResult>;
76
77
  export declare function createReference(): (collection: string) => z.ZodPipe<z.ZodUnion<readonly [z.ZodPipe<z.ZodNumber, z.ZodTransform<string, number>>, z.ZodString, z.ZodObject<{
@@ -1,5 +1,4 @@
1
1
  import { escape } from "html-escaper";
2
- import { forEach } from "neotraverse";
3
2
  import * as z from "zod/v4";
4
3
  import { createSvgComponent } from "../assets/runtime.js";
5
4
  import { imageSrcToImportId } from "../assets/utils/resolveImports.js";
@@ -17,7 +16,6 @@ import {
17
16
  unescapeHTML
18
17
  } from "../runtime/server/index.js";
19
18
  import { defineCollection as defineCollectionOrig } from "./config.js";
20
- import { IMAGE_IMPORT_PREFIX } from "./consts.js";
21
19
  import { globalDataStore } from "./data-store.js";
22
20
  import {
23
21
  LiveCollectionCacheHintError,
@@ -357,33 +355,52 @@ async function updateImageReferencesInBody(html, fileName) {
357
355
  }).filter(([, value]) => value != null).map(([key, value]) => value === "" ? `${key}=""` : `${key}="${escape(String(value))}"`).join(" ");
358
356
  });
359
357
  }
360
- function updateImageReferencesInData(data, fileName, imageAssetMap) {
361
- const copy = structuredClone(data);
362
- forEach(copy, function(ctx, val) {
363
- if (typeof val === "string" && val.startsWith(IMAGE_IMPORT_PREFIX)) {
364
- const src = val.replace(IMAGE_IMPORT_PREFIX, "");
365
- const id = imageSrcToImportId(src, fileName);
366
- if (!id) {
367
- ctx.update(src);
368
- return;
369
- }
370
- const imported = imageAssetMap?.get(id);
371
- if (imported) {
372
- if (imported.__svgData) {
373
- const { __svgData: svgData, ...meta } = imported;
374
- ctx.update(createSvgComponent({ meta, ...svgData }));
375
- } else {
376
- ctx.update(imported);
377
- }
378
- } else {
379
- ctx.update(src);
380
- }
381
- }
382
- });
358
+ function resolveImageAtPath(src, fileName, imageAssetMap) {
359
+ const id = imageSrcToImportId(src, fileName);
360
+ if (!id) {
361
+ return void 0;
362
+ }
363
+ const imported = imageAssetMap?.get(id);
364
+ if (!imported) {
365
+ return void 0;
366
+ }
367
+ if (imported.__svgData) {
368
+ const { __svgData: svgData, ...meta } = imported;
369
+ return createSvgComponent({ meta, ...svgData });
370
+ }
371
+ return imported;
372
+ }
373
+ function setAtPathCopying(target, path, value) {
374
+ if (path.length === 0) {
375
+ return target;
376
+ }
377
+ const [key, ...rest] = path;
378
+ const copy = Array.isArray(target) ? target.slice() : { ...target };
379
+ copy[key] = rest.length === 0 ? value : setAtPathCopying(copy[key], rest, value);
383
380
  return copy;
384
381
  }
382
+ function updateImageReferencesInData(data, fileName, imageAssetMap, imageImports) {
383
+ if (!imageImports?.length) {
384
+ return data;
385
+ }
386
+ let result = data;
387
+ for (const path of imageImports) {
388
+ let src = result;
389
+ for (const key of path) {
390
+ src = src?.[key];
391
+ }
392
+ if (typeof src !== "string") {
393
+ continue;
394
+ }
395
+ const resolved = resolveImageAtPath(src, fileName, imageAssetMap);
396
+ if (resolved !== void 0) {
397
+ result = setAtPathCopying(result, path, resolved);
398
+ }
399
+ }
400
+ return result;
401
+ }
385
402
  function resolveEntryData(entry, imageAssetMap) {
386
- return entry.assetImports?.length ? updateImageReferencesInData(entry.data, entry.filePath, imageAssetMap) : structuredClone(entry.data);
403
+ return updateImageReferencesInData(entry.data, entry.filePath, imageAssetMap, entry.imageImports);
387
404
  }
388
405
  async function renderEntry(entry) {
389
406
  if (!entry) {
@@ -1,7 +1,5 @@
1
1
  import { BaseApp, type LogRequestPayload } from './base.js';
2
- import { AppPipeline } from './pipeline.js';
3
2
  export declare class App extends BaseApp {
4
- createPipeline(streaming: boolean): AppPipeline;
5
3
  isDev(): boolean;
6
4
  logRequest(_options: LogRequestPayload): void;
7
5
  }
@@ -1,12 +1,5 @@
1
1
  import { BaseApp } from "./base.js";
2
- import { AppPipeline } from "./pipeline.js";
3
2
  class App extends BaseApp {
4
- createPipeline(streaming) {
5
- return AppPipeline.create({
6
- manifest: this.manifest,
7
- streaming
8
- });
9
- }
10
3
  isDev() {
11
4
  return false;
12
5
  }
@@ -1,12 +1,10 @@
1
1
  import type { RoutesList } from '../../types/astro.js';
2
2
  import type { RemotePattern, RouteData } from '../../types/public/index.js';
3
- import { type Pipeline } from '../base-pipeline.js';
4
3
  import { getSetCookiesFromResponse } from '../cookies/index.js';
5
4
  import { AstroIntegrationLogger, type AstroLogger } from '../logger/core.js';
6
5
  import type { FetchHandler } from '../fetch/types.js';
7
- import type { ErrorHandler } from '../errors/handler.js';
6
+ import { type ErrorHandler } from '../errors/handler.js';
8
7
  import type { WaitUntilHook } from '../wait-until.js';
9
- import type { AppPipeline } from './pipeline.js';
10
8
  import type { SSRManifest } from './types.js';
11
9
  export interface DevMatch {
12
10
  routeData: RouteData;
@@ -87,17 +85,38 @@ export interface RenderErrorOptions extends ResolvedRenderOptions {
87
85
  pathname?: string;
88
86
  }
89
87
  type ErrorPagePath = `${string}/404` | `${string}/500` | `${string}/404/` | `${string}/500/` | `${string}/404/index.html` | `${string}/500/index.html` | `${string}404.html` | `${string}500.html`;
90
- export declare abstract class BaseApp<P extends Pipeline = AppPipeline> {
88
+ export declare abstract class BaseApp {
91
89
  #private;
92
90
  manifest: SSRManifest;
93
- manifestData: {
94
- routes: RouteData[];
95
- };
96
- pipeline: P;
97
91
  baseWithoutTrailingSlash: string;
98
92
  get logger(): AstroLogger;
93
+ /**
94
+ * Route data derived from the manifest, used for route matching. Reads and
95
+ * writes go through the single per-manifest route table, so HMR updates are
96
+ * visible to every consumer at once.
97
+ */
98
+ get manifestData(): {
99
+ routes: RouteData[];
100
+ };
101
+ set manifestData(routesList: {
102
+ routes: RouteData[];
103
+ });
99
104
  get adapterLogger(): AstroIntegrationLogger;
100
- constructor(manifest: SSRManifest, streaming?: boolean, ...args: any[]);
105
+ constructor(manifest: SSRManifest, streaming?: boolean);
106
+ /**
107
+ * Resolves the user-configured logger destination from the manifest and
108
+ * returns the logger. Lazy and only resolves once; safe to call before
109
+ * the first render (adapters use this to log startup messages through
110
+ * the configured destination).
111
+ */
112
+ getLogger(): Promise<AstroLogger>;
113
+ /**
114
+ * The streaming flag fed into the internal `FetchState` facade hooks on
115
+ * the fast path. Returns the constructor flag by
116
+ * default; `BuildApp` overrides this to return `undefined` so streaming
117
+ * falls through to the environment default (`manifest.serverLike`).
118
+ */
119
+ protected resolveStreaming(): boolean | undefined;
101
120
  /**
102
121
  * Override the fetch handler used to dispatch requests. Entrypoints
103
122
  * call this with the default export of `virtual:astro:fetchable` to
@@ -107,8 +126,10 @@ export declare abstract class BaseApp<P extends Pipeline = AppPipeline> {
107
126
  fetch: FetchHandler;
108
127
  }): void;
109
128
  /**
110
- * Returns the error handler strategy used by this app. Override to
111
- * provide environment-specific behavior (dev overlay, build-time throws, etc.).
129
+ * Returns the error handler used by this app. The default is a thin
130
+ * bridge over the functional error API strategy selection (production
131
+ * default / dev / build) is environment-driven inside `renderErrorPage`.
132
+ * External subclasses can override this to customize error rendering.
112
133
  */
113
134
  protected createErrorHandler(): ErrorHandler;
114
135
  abstract isDev(): boolean;
@@ -120,15 +141,6 @@ export declare abstract class BaseApp<P extends Pipeline = AppPipeline> {
120
141
  getAllowedDomains(): Partial<RemotePattern>[] | undefined;
121
142
  protected matchesAllowedDomains(forwardedHost: string, protocol?: string): boolean;
122
143
  static validateForwardedHost(forwardedHost: string, allowedDomains?: Partial<RemotePattern>[], protocol?: string): boolean;
123
- /**
124
- * Creates a pipeline by reading the stored manifest
125
- *
126
- * @param streaming
127
- * @param manifest
128
- * @param args
129
- * @private
130
- */
131
- abstract createPipeline(streaming: boolean, manifest: SSRManifest, ...args: any[]): P;
132
144
  set setManifestData(newManifestData: RoutesList);
133
145
  removeBase(pathname: string): string;
134
146
  /**