astro 7.1.6 → 7.2.0
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/assets/build/generate.d.ts +8 -1
- package/dist/assets/build/generate.js +21 -1
- package/dist/assets/fonts/providers/index.js +12 -2
- package/dist/assets/types.d.ts +13 -0
- package/dist/assets/vite-plugin-assets.js +8 -0
- package/dist/cli/add/index.js +1 -1
- package/dist/cli/agent.d.ts +1 -0
- package/dist/cli/agent.js +11 -0
- package/dist/cli/dev/background.d.ts +3 -16
- package/dist/cli/dev/background.js +7 -93
- package/dist/cli/dev/index.d.ts +12 -0
- package/dist/cli/dev/index.js +30 -23
- package/dist/cli/dev/logs.js +2 -64
- package/dist/cli/dev/status.d.ts +2 -9
- package/dist/cli/dev/status.js +6 -24
- package/dist/cli/dev/stop.d.ts +2 -6
- package/dist/cli/dev/stop.js +6 -14
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/cli/install-package.js +1 -1
- package/dist/cli/preview/index.js +77 -3
- package/dist/cli/server.d.ts +60 -0
- package/dist/cli/server.js +274 -0
- package/dist/content/content-layer.js +3 -3
- package/dist/content/runtime.d.ts +2 -0
- package/dist/content/runtime.js +2 -0
- package/dist/content/types-generator.js +1 -0
- package/dist/content/vite-plugin-content-assets.js +6 -1
- package/dist/content/vite-plugin-content-imports.js +12 -3
- package/dist/content/vite-plugin-content-virtual-mod.js +28 -16
- package/dist/core/app/entrypoints/index.d.ts +2 -0
- package/dist/core/app/entrypoints/index.js +14 -0
- package/dist/core/build/config-hash/index.d.ts +8 -0
- package/dist/core/build/config-hash/index.js +23 -0
- package/dist/core/build/config-hash/input.d.ts +199 -0
- package/dist/core/build/config-hash/input.js +43 -0
- package/dist/core/build/generate.d.ts +3 -1
- package/dist/core/build/generate.js +149 -14
- package/dist/core/build/incremental-content-collector.d.ts +10 -0
- package/dist/core/build/incremental-content-collector.js +33 -0
- package/dist/core/build/incremental-image-collector.d.ts +11 -0
- package/dist/core/build/incremental-image-collector.js +32 -0
- package/dist/core/build/incremental-metadata.d.ts +9 -0
- package/dist/core/build/incremental-metadata.js +17 -0
- package/dist/core/build/incremental.d.ts +123 -0
- package/dist/core/build/incremental.js +178 -0
- package/dist/core/build/index.d.ts +3 -0
- package/dist/core/build/index.js +6 -2
- package/dist/core/build/internal.d.ts +19 -0
- package/dist/core/build/lockfile/finder.d.ts +22 -0
- package/dist/core/build/lockfile/finder.js +45 -0
- package/dist/core/build/lockfile/hasher.d.ts +16 -0
- package/dist/core/build/lockfile/hasher.js +46 -0
- package/dist/core/build/lockfile/index.d.ts +9 -0
- package/dist/core/build/lockfile/index.js +16 -0
- package/dist/core/build/plugins/index.js +3 -1
- package/dist/core/build/plugins/plugin-incremental.d.ts +14 -0
- package/dist/core/build/plugins/plugin-incremental.js +134 -0
- package/dist/core/build/types.d.ts +2 -0
- package/dist/core/config/schemas/base.d.ts +3 -2
- package/dist/core/config/schemas/base.js +1 -0
- package/dist/core/config/schemas/defaults.d.ts +1 -0
- package/dist/core/config/schemas/defaults.js +1 -0
- package/dist/core/config/schemas/relative.d.ts +7 -4
- package/dist/core/constants.js +1 -1
- package/dist/core/create-vite.js +2 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/dev/lockfile.d.ts +8 -7
- package/dist/core/dev/lockfile.js +13 -13
- package/dist/core/encryption.d.ts +6 -0
- package/dist/core/encryption.js +14 -2
- package/dist/core/errors/default-handler.js +4 -5
- package/dist/core/fetch/index.js +1 -1
- package/dist/core/logger/config.d.ts +1 -1
- package/dist/core/logger/load.d.ts +3 -1
- package/dist/core/logger/load.js +3 -3
- package/dist/core/logger/utils.d.ts +6 -4
- package/dist/core/logger/utils.js +13 -5
- package/dist/core/logger/vite-plugin.js +1 -1
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/preview/static-preview-server.d.ts +2 -0
- package/dist/core/preview/static-preview-server.js +1 -0
- package/dist/core/routing/handler.js +1 -1
- package/dist/core/session/config.d.ts +2 -2
- package/dist/core/session/config.js +2 -1
- package/dist/core/session/provider-disabled.d.ts +2 -0
- package/dist/core/session/provider-disabled.js +7 -0
- package/dist/core/session/provider.d.ts +1 -0
- package/dist/core/session/provider.js +4 -0
- package/dist/core/session/utils.js +3 -0
- package/dist/core/session/vite-plugin.d.ts +3 -0
- package/dist/core/session/vite-plugin.js +41 -6
- package/dist/integrations/hooks.js +3 -1
- package/dist/runtime/prerender/static-paths.js +5 -1
- package/dist/runtime/server/render/util.js +3 -0
- package/dist/types/public/common.d.ts +1 -0
- package/dist/types/public/config.d.ts +59 -2
- package/dist/types/public/integrations.d.ts +29 -2
- package/dist/types/public/preview.d.ts +2 -0
- package/dist/vite-plugin-config-alias/index.js +1 -0
- package/dist/vite-plugin-environment/index.js +4 -1
- package/package.json +1 -2
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { PROPAGATED_ASSET_FLAG } from "../../../content/consts.js";
|
|
3
|
+
import { hasContentFlag } from "../../../content/utils.js";
|
|
4
|
+
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
|
|
5
|
+
import { removeQueryString } from "../../path.js";
|
|
6
|
+
import { rootRelativePath } from "../../viteUtils.js";
|
|
7
|
+
import { moduleIsTopLevelPage } from "../graph.js";
|
|
8
|
+
import { isContentDataIncrementalModule } from "../incremental-metadata.js";
|
|
9
|
+
import { getPageDataByViteID } from "../internal.js";
|
|
10
|
+
function collectTransitiveDeps(graph, rootId) {
|
|
11
|
+
const deps = /* @__PURE__ */ new Set();
|
|
12
|
+
const queue = [rootId];
|
|
13
|
+
while (queue.length > 0) {
|
|
14
|
+
const current = queue.pop();
|
|
15
|
+
if (deps.has(current)) continue;
|
|
16
|
+
const modInfo = graph.getModuleInfo(current);
|
|
17
|
+
if (isContentDataIncrementalModule(modInfo)) continue;
|
|
18
|
+
deps.add(current);
|
|
19
|
+
if (!modInfo) continue;
|
|
20
|
+
for (const dep of modInfo.importedIds) {
|
|
21
|
+
if (!deps.has(dep)) queue.push(dep);
|
|
22
|
+
}
|
|
23
|
+
for (const dep of modInfo.dynamicallyImportedIds) {
|
|
24
|
+
if (!deps.has(dep)) queue.push(dep);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return [...deps].sort();
|
|
28
|
+
}
|
|
29
|
+
function hashModules(graph, sortedIds) {
|
|
30
|
+
const hasher = crypto.createHash("sha256");
|
|
31
|
+
for (const id of sortedIds) {
|
|
32
|
+
hasher.update(id);
|
|
33
|
+
hasher.update("\n");
|
|
34
|
+
const code = graph.getModuleInfo(id)?.code;
|
|
35
|
+
if (code != null) {
|
|
36
|
+
hasher.update(code);
|
|
37
|
+
}
|
|
38
|
+
hasher.update("\n");
|
|
39
|
+
}
|
|
40
|
+
return hasher.digest("hex");
|
|
41
|
+
}
|
|
42
|
+
function collectClientEntrypointHashes(graph, entrypointIds, pagesByEntrypoint, hashesByComponent) {
|
|
43
|
+
for (const entrypointId of entrypointIds) {
|
|
44
|
+
const pages = pagesByEntrypoint.get(entrypointId);
|
|
45
|
+
if (!pages?.size) continue;
|
|
46
|
+
const hash = hashModules(graph, collectTransitiveDeps(graph, entrypointId));
|
|
47
|
+
for (const pageData of pages) {
|
|
48
|
+
let list = hashesByComponent.get(pageData.component);
|
|
49
|
+
if (!list) {
|
|
50
|
+
list = [];
|
|
51
|
+
hashesByComponent.set(pageData.component, list);
|
|
52
|
+
}
|
|
53
|
+
list.push(hash);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function foldClientDependencies(graph, internals) {
|
|
58
|
+
const baseHashes = internals.pageDependencyHashes;
|
|
59
|
+
if (!baseHashes) return;
|
|
60
|
+
const hashesByComponent = /* @__PURE__ */ new Map();
|
|
61
|
+
collectClientEntrypointHashes(
|
|
62
|
+
graph,
|
|
63
|
+
internals.discoveredClientOnlyComponents.keys(),
|
|
64
|
+
internals.pagesByClientOnly,
|
|
65
|
+
hashesByComponent
|
|
66
|
+
);
|
|
67
|
+
collectClientEntrypointHashes(
|
|
68
|
+
graph,
|
|
69
|
+
internals.discoveredScripts,
|
|
70
|
+
internals.pagesByScriptId,
|
|
71
|
+
hashesByComponent
|
|
72
|
+
);
|
|
73
|
+
for (const [component, clientHashes] of hashesByComponent) {
|
|
74
|
+
const hasher = crypto.createHash("sha256");
|
|
75
|
+
hasher.update(baseHashes.get(component) ?? "");
|
|
76
|
+
for (const hash of clientHashes.sort()) {
|
|
77
|
+
hasher.update("\n");
|
|
78
|
+
hasher.update(hash);
|
|
79
|
+
}
|
|
80
|
+
baseHashes.set(component, hasher.digest("hex"));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function collectContentEntryHashes(graph, root) {
|
|
84
|
+
const entryHashes = /* @__PURE__ */ new Map();
|
|
85
|
+
for (const id of graph.getModuleIds()) {
|
|
86
|
+
if (!hasContentFlag(id, PROPAGATED_ASSET_FLAG)) continue;
|
|
87
|
+
const renderModuleId = removeQueryString(id);
|
|
88
|
+
const key = rootRelativePath(root, renderModuleId, false);
|
|
89
|
+
const deps = collectTransitiveDeps(graph, renderModuleId);
|
|
90
|
+
entryHashes.set(key, hashModules(graph, deps));
|
|
91
|
+
}
|
|
92
|
+
return entryHashes;
|
|
93
|
+
}
|
|
94
|
+
function pageContainsServerIsland(graph, ids) {
|
|
95
|
+
for (const id of ids) {
|
|
96
|
+
const serverComponents = graph.getModuleInfo(id)?.meta?.astro?.serverComponents;
|
|
97
|
+
if (serverComponents?.length) return true;
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
function pluginIncremental(internals, root) {
|
|
102
|
+
return {
|
|
103
|
+
name: "@astro/plugin-incremental",
|
|
104
|
+
applyToEnvironment(environment) {
|
|
105
|
+
return environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender || environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client;
|
|
106
|
+
},
|
|
107
|
+
generateBundle() {
|
|
108
|
+
if (this.environment?.name === ASTRO_VITE_ENVIRONMENT_NAMES.client) {
|
|
109
|
+
foldClientDependencies(this, internals);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const hashes = /* @__PURE__ */ new Map();
|
|
113
|
+
const serverIslandComponents = /* @__PURE__ */ new Set();
|
|
114
|
+
for (const id of this.getModuleIds()) {
|
|
115
|
+
const info = this.getModuleInfo(id);
|
|
116
|
+
if (!info) continue;
|
|
117
|
+
if (!moduleIsTopLevelPage(info)) continue;
|
|
118
|
+
const pageData = getPageDataByViteID(internals, info.id);
|
|
119
|
+
if (!pageData) continue;
|
|
120
|
+
const deps = collectTransitiveDeps(this, info.id);
|
|
121
|
+
hashes.set(pageData.component, hashModules(this, deps));
|
|
122
|
+
if (pageContainsServerIsland(this, deps)) {
|
|
123
|
+
serverIslandComponents.add(pageData.component);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
internals.pageDependencyHashes = hashes;
|
|
127
|
+
internals.contentEntryRenderHashes = collectContentEntryHashes(this, root);
|
|
128
|
+
internals.serverIslandPageComponents = serverIslandComponents;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
export {
|
|
133
|
+
pluginIncremental
|
|
134
|
+
};
|
|
@@ -38,6 +38,8 @@ export interface StaticBuildOptions {
|
|
|
38
38
|
pageNames: string[];
|
|
39
39
|
viteConfig: InlineConfig;
|
|
40
40
|
key: Promise<CryptoKey>;
|
|
41
|
+
/** Set by `astro build --force` to rebuild every page and ignore the incremental cache. */
|
|
42
|
+
force: boolean;
|
|
41
43
|
}
|
|
42
44
|
type ImportComponentInstance = () => Promise<ComponentInstance>;
|
|
43
45
|
export interface SinglePageBuiltModule {
|
|
@@ -393,7 +393,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
393
393
|
}, z.core.$strip>]>>>>>;
|
|
394
394
|
validateSecrets: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
395
395
|
}, z.core.$strict>>>;
|
|
396
|
-
session: z.ZodOptional<z.ZodObject<{
|
|
396
|
+
session: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
|
|
397
397
|
driver: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
398
398
|
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
399
399
|
entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
|
|
@@ -414,7 +414,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
414
414
|
name: string;
|
|
415
415
|
}, string>>]>>;
|
|
416
416
|
ttl: z.ZodOptional<z.ZodNumber>;
|
|
417
|
-
}, z.core.$strip>>;
|
|
417
|
+
}, z.core.$strip>]>>;
|
|
418
418
|
prerenderConflictBehavior: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
419
419
|
error: "error";
|
|
420
420
|
ignore: "ignore";
|
|
@@ -484,6 +484,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
484
484
|
clientPrerender: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
485
485
|
contentIntellisense: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
486
486
|
chromeDevtoolsWorkspace: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
487
|
+
incrementalBuild: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
487
488
|
svgOptimizer: z.ZodOptional<z.ZodObject<{
|
|
488
489
|
name: z.ZodString;
|
|
489
490
|
optimize: z.ZodCustom<(contents: string) => string | Promise<string>, (contents: string) => string | Promise<string>>;
|
|
@@ -276,6 +276,7 @@ const AstroConfigSchema = z.object({
|
|
|
276
276
|
clientPrerender: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.clientPrerender),
|
|
277
277
|
contentIntellisense: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.contentIntellisense),
|
|
278
278
|
chromeDevtoolsWorkspace: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.chromeDevtoolsWorkspace),
|
|
279
|
+
incrementalBuild: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.incrementalBuild),
|
|
279
280
|
svgOptimizer: SvgOptimizerSchema.optional(),
|
|
280
281
|
collectionStorage: z.union([
|
|
281
282
|
z.literal("single-file"),
|
|
@@ -345,7 +345,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
345
345
|
}, z.core.$strip>]>>>>>;
|
|
346
346
|
validateSecrets: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
347
347
|
}, z.core.$strict>>>;
|
|
348
|
-
session: z.ZodOptional<z.ZodObject<{
|
|
348
|
+
session: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
|
|
349
349
|
driver: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
350
350
|
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
351
351
|
entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
|
|
@@ -366,7 +366,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
366
366
|
name: string;
|
|
367
367
|
}, string>>]>>;
|
|
368
368
|
ttl: z.ZodOptional<z.ZodNumber>;
|
|
369
|
-
}, z.core.$strip>>;
|
|
369
|
+
}, z.core.$strip>]>>;
|
|
370
370
|
prerenderConflictBehavior: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
371
371
|
error: "error";
|
|
372
372
|
ignore: "ignore";
|
|
@@ -436,6 +436,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
436
436
|
clientPrerender: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
437
437
|
contentIntellisense: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
438
438
|
chromeDevtoolsWorkspace: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
439
|
+
incrementalBuild: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
439
440
|
svgOptimizer: z.ZodOptional<z.ZodObject<{
|
|
440
441
|
name: z.ZodString;
|
|
441
442
|
optimize: z.ZodCustom<(contents: string) => string | Promise<string>, (contents: string) => string | Promise<string>>;
|
|
@@ -630,6 +631,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
630
631
|
clientPrerender: boolean;
|
|
631
632
|
contentIntellisense: boolean;
|
|
632
633
|
chromeDevtoolsWorkspace: boolean;
|
|
634
|
+
incrementalBuild: boolean;
|
|
633
635
|
collectionStorage: "single-file" | "chunked" | {
|
|
634
636
|
type: "chunked";
|
|
635
637
|
chunkSize: number;
|
|
@@ -693,7 +695,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
693
695
|
domains?: Record<string, string> | undefined;
|
|
694
696
|
fallback?: Record<string, string> | undefined;
|
|
695
697
|
} | undefined;
|
|
696
|
-
session?: {
|
|
698
|
+
session?: false | {
|
|
697
699
|
driver?: string | {
|
|
698
700
|
entrypoint: string | URL;
|
|
699
701
|
config?: Record<string, any> | undefined;
|
|
@@ -896,6 +898,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
896
898
|
clientPrerender: boolean;
|
|
897
899
|
contentIntellisense: boolean;
|
|
898
900
|
chromeDevtoolsWorkspace: boolean;
|
|
901
|
+
incrementalBuild: boolean;
|
|
899
902
|
collectionStorage: "single-file" | "chunked" | {
|
|
900
903
|
type: "chunked";
|
|
901
904
|
chunkSize: number;
|
|
@@ -959,7 +962,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
959
962
|
domains?: Record<string, string> | undefined;
|
|
960
963
|
fallback?: Record<string, string> | undefined;
|
|
961
964
|
} | undefined;
|
|
962
|
-
session?: {
|
|
965
|
+
session?: false | {
|
|
963
966
|
driver?: string | {
|
|
964
967
|
entrypoint: string | URL;
|
|
965
968
|
config?: Record<string, any> | undefined;
|
package/dist/core/constants.js
CHANGED
package/dist/core/create-vite.js
CHANGED
|
@@ -47,7 +47,7 @@ import { joinPaths } from "./path.js";
|
|
|
47
47
|
import { ServerIslandsState } from "./server-islands/shared-state.js";
|
|
48
48
|
import { vitePluginServerIslands } from "./server-islands/vite-plugin-server-islands.js";
|
|
49
49
|
import { vitePluginCacheProvider } from "./cache/vite-plugin.js";
|
|
50
|
-
import { vitePluginSessionDriver } from "./session/vite-plugin.js";
|
|
50
|
+
import { vitePluginSessionDriver, vitePluginSessionProvider } from "./session/vite-plugin.js";
|
|
51
51
|
import { vitePluginLogger } from "./logger/vite-plugin.js";
|
|
52
52
|
import { isObject } from "./util-runtime.js";
|
|
53
53
|
import { vitePluginEnvironment } from "../vite-plugin-environment/index.js";
|
|
@@ -180,6 +180,7 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
|
|
|
180
180
|
vitePluginActions({ fs, settings }),
|
|
181
181
|
vitePluginServerIslands({ settings, logger, serverIslandsState }),
|
|
182
182
|
vitePluginSessionDriver({ settings }),
|
|
183
|
+
vitePluginSessionProvider({ settings }),
|
|
183
184
|
vitePluginCacheProvider({ settings }),
|
|
184
185
|
vitePluginLogger({ settings }),
|
|
185
186
|
astroContainer(),
|
package/dist/core/dev/dev.js
CHANGED
|
@@ -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.
|
|
29
|
+
const currentVersion = "7.2.0";
|
|
30
30
|
const isPrerelease = currentVersion.includes("-");
|
|
31
31
|
if (!isPrerelease) {
|
|
32
32
|
try {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ResolvedServerUrls } from 'vite';
|
|
2
|
+
export type ServerCommand = 'dev' | 'preview';
|
|
2
3
|
/** Maximum time (ms) to wait for a process to exit after SIGTERM before escalating to SIGKILL. */
|
|
3
4
|
export declare const GRACEFUL_SHUTDOWN_TIMEOUT = 5000;
|
|
4
5
|
export interface LockFileData {
|
|
@@ -14,9 +15,9 @@ export interface ExistingServer {
|
|
|
14
15
|
stale: boolean;
|
|
15
16
|
}
|
|
16
17
|
/**
|
|
17
|
-
* Get the URL of
|
|
18
|
+
* Get the URL of a server log file for a given project root.
|
|
18
19
|
*/
|
|
19
|
-
export declare function getLogFileURL(root: URL): URL;
|
|
20
|
+
export declare function getLogFileURL(root: URL, command?: ServerCommand): URL;
|
|
20
21
|
/**
|
|
21
22
|
* Parse a lock file JSON string into a LockFileData object.
|
|
22
23
|
* Returns null if the content is invalid.
|
|
@@ -34,15 +35,15 @@ export declare function isProcessAlive(pid: number): boolean;
|
|
|
34
35
|
/**
|
|
35
36
|
* Read the lock file from disk. Returns null if it doesn't exist or is invalid.
|
|
36
37
|
*/
|
|
37
|
-
export declare function readLockFile(root: URL): LockFileData | null;
|
|
38
|
+
export declare function readLockFile(root: URL, command?: ServerCommand): LockFileData | null;
|
|
38
39
|
/**
|
|
39
40
|
* Write the lock file to disk.
|
|
40
41
|
*/
|
|
41
|
-
export declare function writeLockFile(root: URL, data: LockFileData): void;
|
|
42
|
+
export declare function writeLockFile(root: URL, data: LockFileData, command?: ServerCommand): void;
|
|
42
43
|
/**
|
|
43
44
|
* Remove the lock file from disk. No-op if it doesn't exist.
|
|
44
45
|
*/
|
|
45
|
-
export declare function removeLockFile(root: URL): void;
|
|
46
|
+
export declare function removeLockFile(root: URL, command?: ServerCommand): void;
|
|
46
47
|
/**
|
|
47
48
|
* Given lock file data and a liveness result, determine the state of the existing server.
|
|
48
49
|
* This is the pure decision logic, separated from I/O for testability.
|
|
@@ -57,8 +58,8 @@ export declare function evaluateExistingServer(data: LockFileData | null, alive:
|
|
|
57
58
|
*/
|
|
58
59
|
export declare function killDevServer(root: URL, data: LockFileData): Promise<void>;
|
|
59
60
|
/**
|
|
60
|
-
* Check for an existing
|
|
61
|
+
* Check for an existing server by reading the lock file and checking process liveness.
|
|
61
62
|
* Automatically cleans up stale lock files.
|
|
62
63
|
* Returns the server info if a live server is found, null otherwise.
|
|
63
64
|
*/
|
|
64
|
-
export declare function checkExistingServer(root: URL): LockFileData | null;
|
|
65
|
+
export declare function checkExistingServer(root: URL, command?: ServerCommand): LockFileData | null;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { existsSync, readFileSync, unlinkSync, writeFileSync, mkdirSync } from "node:fs";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
const GRACEFUL_SHUTDOWN_TIMEOUT = 5e3;
|
|
4
|
-
function getLockFileURL(root) {
|
|
5
|
-
return new URL(
|
|
4
|
+
function getLockFileURL(root, command = "dev") {
|
|
5
|
+
return new URL(`.astro/${command}.json`, root);
|
|
6
6
|
}
|
|
7
|
-
function getLogFileURL(root) {
|
|
8
|
-
return new URL(
|
|
7
|
+
function getLogFileURL(root, command = "dev") {
|
|
8
|
+
return new URL(`.astro/${command}.log`, root);
|
|
9
9
|
}
|
|
10
10
|
function isStringArray(value) {
|
|
11
11
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
@@ -42,8 +42,8 @@ function isProcessAlive(pid) {
|
|
|
42
42
|
return false;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
function readLockFile(root) {
|
|
46
|
-
const lockFileURL = getLockFileURL(root);
|
|
45
|
+
function readLockFile(root, command = "dev") {
|
|
46
|
+
const lockFileURL = getLockFileURL(root, command);
|
|
47
47
|
try {
|
|
48
48
|
const content = readFileSync(lockFileURL, "utf-8");
|
|
49
49
|
return parseLockFile(content);
|
|
@@ -51,8 +51,8 @@ function readLockFile(root) {
|
|
|
51
51
|
return null;
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
function writeLockFile(root, data) {
|
|
55
|
-
const lockFileURL = getLockFileURL(root);
|
|
54
|
+
function writeLockFile(root, data, command = "dev") {
|
|
55
|
+
const lockFileURL = getLockFileURL(root, command);
|
|
56
56
|
const dirPath = fileURLToPath(new URL(".astro/", root));
|
|
57
57
|
try {
|
|
58
58
|
if (!existsSync(dirPath)) {
|
|
@@ -64,8 +64,8 @@ function writeLockFile(root, data) {
|
|
|
64
64
|
throw new Error(`Failed to write lock file: ${message}`);
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
-
function removeLockFile(root) {
|
|
68
|
-
const lockFileURL = getLockFileURL(root);
|
|
67
|
+
function removeLockFile(root, command = "dev") {
|
|
68
|
+
const lockFileURL = getLockFileURL(root, command);
|
|
69
69
|
try {
|
|
70
70
|
unlinkSync(lockFileURL);
|
|
71
71
|
} catch (err) {
|
|
@@ -98,14 +98,14 @@ async function killDevServer(root, data) {
|
|
|
98
98
|
}
|
|
99
99
|
removeLockFile(root);
|
|
100
100
|
}
|
|
101
|
-
function checkExistingServer(root) {
|
|
102
|
-
const data = readLockFile(root);
|
|
101
|
+
function checkExistingServer(root, command = "dev") {
|
|
102
|
+
const data = readLockFile(root, command);
|
|
103
103
|
const result = evaluateExistingServer(data, data !== null && isProcessAlive(data.pid));
|
|
104
104
|
if (result === null) {
|
|
105
105
|
return null;
|
|
106
106
|
}
|
|
107
107
|
if (result.stale) {
|
|
108
|
-
removeLockFile(root);
|
|
108
|
+
removeLockFile(root, command);
|
|
109
109
|
return null;
|
|
110
110
|
}
|
|
111
111
|
return result.data;
|
|
@@ -12,6 +12,12 @@ export declare function hasEnvironmentKey(): boolean;
|
|
|
12
12
|
* Get the environment variable key and decode it into a CryptoKey.
|
|
13
13
|
*/
|
|
14
14
|
export declare function getEnvironmentKey(): Promise<CryptoKey>;
|
|
15
|
+
/**
|
|
16
|
+
* Hash a CryptoKey into a one-way hex digest safe to persist. Server-island
|
|
17
|
+
* ciphertext is bound to the key, so the incremental build cache uses this to
|
|
18
|
+
* detect when the key changed between builds.
|
|
19
|
+
*/
|
|
20
|
+
export declare function hashCryptoKey(key: CryptoKey): Promise<string>;
|
|
15
21
|
/**
|
|
16
22
|
* Encodes a CryptoKey to base64 string, so that it can be embedded in JSON / JavaScript
|
|
17
23
|
*/
|
package/dist/core/encryption.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
decodeBase64,
|
|
3
|
+
decodeHex,
|
|
4
|
+
encodeBase64,
|
|
5
|
+
encodeHexLowerCase,
|
|
6
|
+
encodeHexUpperCase
|
|
7
|
+
} from "@oslojs/encoding";
|
|
2
8
|
import { ALGORITHMS } from "./csp/config.js";
|
|
3
9
|
const ALGORITHM = "AES-GCM";
|
|
4
10
|
async function createKey() {
|
|
@@ -28,6 +34,11 @@ async function getEnvironmentKey() {
|
|
|
28
34
|
const encodedKey = getEncodedEnvironmentKey();
|
|
29
35
|
return decodeKey(encodedKey);
|
|
30
36
|
}
|
|
37
|
+
async function hashCryptoKey(key) {
|
|
38
|
+
const exported = await crypto.subtle.exportKey("raw", key);
|
|
39
|
+
const digest = await crypto.subtle.digest("SHA-256", exported);
|
|
40
|
+
return encodeHexLowerCase(new Uint8Array(digest));
|
|
41
|
+
}
|
|
31
42
|
async function encodeKey(key) {
|
|
32
43
|
const exported = await crypto.subtle.exportKey("raw", key);
|
|
33
44
|
const encodedKey = encodeBase64(new Uint8Array(exported));
|
|
@@ -83,5 +94,6 @@ export {
|
|
|
83
94
|
generateContentHash,
|
|
84
95
|
generateCspDigest,
|
|
85
96
|
getEnvironmentKey,
|
|
86
|
-
hasEnvironmentKey
|
|
97
|
+
hasEnvironmentKey,
|
|
98
|
+
hashCryptoKey
|
|
87
99
|
};
|
|
@@ -5,7 +5,7 @@ import { getCookiesFromResponse } from "../cookies/response.js";
|
|
|
5
5
|
import { AstroMiddleware } from "../middleware/astro-middleware.js";
|
|
6
6
|
import { PagesHandler } from "../pages/handler.js";
|
|
7
7
|
import { matchRoute } from "../routing/match.js";
|
|
8
|
-
import { provideSession } from "../session/
|
|
8
|
+
import { provideSession } from "../session/provider.js";
|
|
9
9
|
import { validateHost } from "../app/validate-headers.js";
|
|
10
10
|
import { getErrorRoutePath } from "../../i18n/error-routes.js";
|
|
11
11
|
import { getOutputFilename } from "../output-filename.js";
|
|
@@ -152,7 +152,8 @@ function mergeResponses(newResponse, originalResponse, override) {
|
|
|
152
152
|
seen.add(name.toLowerCase());
|
|
153
153
|
}
|
|
154
154
|
for (const [name, value] of newResponseHeaders) {
|
|
155
|
-
|
|
155
|
+
const lower = name.toLowerCase();
|
|
156
|
+
if (!seen.has(lower) || lower === "set-cookie") {
|
|
156
157
|
newHeaders.append(name, value);
|
|
157
158
|
}
|
|
158
159
|
}
|
|
@@ -170,9 +171,7 @@ function mergeResponses(newResponse, originalResponse, override) {
|
|
|
170
171
|
const newCookies = getCookiesFromResponse(newResponse);
|
|
171
172
|
if (originalCookies) {
|
|
172
173
|
if (newCookies) {
|
|
173
|
-
|
|
174
|
-
originalResponse.headers.append("set-cookie", cookieValue);
|
|
175
|
-
}
|
|
174
|
+
originalCookies.merge(newCookies);
|
|
176
175
|
}
|
|
177
176
|
attachCookiesToResponse(mergedResponse, originalCookies);
|
|
178
177
|
} else if (newCookies) {
|
package/dist/core/fetch/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { AstroMiddleware } from "../middleware/astro-middleware.js";
|
|
|
7
7
|
import { PagesHandler } from "../pages/handler.js";
|
|
8
8
|
import { renderRedirect } from "../redirects/render.js";
|
|
9
9
|
import { AstroHandler } from "../routing/handler.js";
|
|
10
|
-
import { provideSession } from "../session/
|
|
10
|
+
import { provideSession } from "../session/provider.js";
|
|
11
11
|
import { TrailingSlashHandler } from "../routing/trailing-slash-handler.js";
|
|
12
12
|
function getApp(request) {
|
|
13
13
|
const app = Reflect.get(request, appSymbol);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export interface LoggerHandlerConfig {
|
|
2
2
|
/** Serializable options used by the driver implementation */
|
|
3
3
|
config?: Record<string, any> | undefined;
|
|
4
|
-
/**
|
|
4
|
+
/** A package import, a path relative to the project root, or a URL */
|
|
5
5
|
entrypoint: string | URL;
|
|
6
6
|
}
|
|
@@ -5,7 +5,9 @@ import type { AstroConfig, AstroInlineConfig } from '../../types/public/index.js
|
|
|
5
5
|
* Loads a logger destination in a Node context, i.e. outside of a built server bundle.
|
|
6
6
|
* Inside the bundle, the destination comes from the `virtual:astro:logger` module instead.
|
|
7
7
|
*/
|
|
8
|
-
export declare function loadLoggerDestination(config: LoggerHandlerConfig
|
|
8
|
+
export declare function loadLoggerDestination(config: LoggerHandlerConfig,
|
|
9
|
+
/** The project root, which relative entrypoints are resolved against */
|
|
10
|
+
root: URL): Promise<AstroLoggerDestination>;
|
|
9
11
|
/**
|
|
10
12
|
* It attempts to load a logger from the entrypoint.
|
|
11
13
|
* If not provided, it creates a new logger instance on the fly.
|
package/dist/core/logger/load.js
CHANGED
|
@@ -19,8 +19,8 @@ async function createDestination(config) {
|
|
|
19
19
|
}
|
|
20
20
|
return logger.default(config.config);
|
|
21
21
|
}
|
|
22
|
-
async function loadLoggerDestination(config) {
|
|
23
|
-
const normalized = normalizeLoggerConfig(config);
|
|
22
|
+
async function loadLoggerDestination(config, root) {
|
|
23
|
+
const normalized = normalizeLoggerConfig(config, root);
|
|
24
24
|
try {
|
|
25
25
|
return await createDestination(normalized);
|
|
26
26
|
} catch (e) {
|
|
@@ -39,7 +39,7 @@ async function loadOrCreateNodeLogger(astroConfig, inlineAstroConfig) {
|
|
|
39
39
|
try {
|
|
40
40
|
if (astroConfig.logger) {
|
|
41
41
|
return new AstroLogger({
|
|
42
|
-
destination: await loadLoggerDestination(astroConfig.logger),
|
|
42
|
+
destination: await loadLoggerDestination(astroConfig.logger, astroConfig.root),
|
|
43
43
|
level: inlineAstroConfig.logLevel ?? "info"
|
|
44
44
|
});
|
|
45
45
|
} else {
|
|
@@ -14,8 +14,10 @@ export interface NormalizedLoggerConfig {
|
|
|
14
14
|
* (see `loadLoggerDestination`), and by applying the same treatment to the handlers
|
|
15
15
|
* composed through `astro/logger/compose`.
|
|
16
16
|
*
|
|
17
|
-
* Concretely,
|
|
18
|
-
* drivers do, since both Vite and `import()` can handle those — while
|
|
19
|
-
* e.g. a package specifier, is left untouched.
|
|
17
|
+
* Concretely, `URL` and relative entrypoints become absolute file paths — mirroring what
|
|
18
|
+
* session drivers do, since both Vite and `import()` can handle those — while any other
|
|
19
|
+
* string entrypoint, e.g. a package specifier, is left untouched.
|
|
20
20
|
*/
|
|
21
|
-
export declare function normalizeLoggerConfig(logger: LoggerHandlerConfig
|
|
21
|
+
export declare function normalizeLoggerConfig(logger: LoggerHandlerConfig,
|
|
22
|
+
/** The project root, which relative entrypoints are resolved against */
|
|
23
|
+
root: URL): NormalizedLoggerConfig;
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
1
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { isRelativePath } from "../path.js";
|
|
2
4
|
const COMPOSE_LOGGER_ENTRYPOINT = "astro/logger/compose";
|
|
3
|
-
function normalizeLoggerConfig(logger) {
|
|
4
|
-
const entrypoint = normalizeEntrypoint(logger.entrypoint);
|
|
5
|
+
function normalizeLoggerConfig(logger, root) {
|
|
6
|
+
const entrypoint = normalizeEntrypoint(logger.entrypoint, root);
|
|
5
7
|
if (entrypoint === COMPOSE_LOGGER_ENTRYPOINT) {
|
|
6
8
|
const loggers = logger.config?.loggers ?? [];
|
|
7
9
|
return {
|
|
8
10
|
entrypoint,
|
|
9
|
-
loggers: loggers.map((nested) => normalizeLoggerConfig(nested))
|
|
11
|
+
loggers: loggers.map((nested) => normalizeLoggerConfig(nested, root))
|
|
10
12
|
};
|
|
11
13
|
}
|
|
12
14
|
return { entrypoint, config: logger.config };
|
|
13
15
|
}
|
|
14
|
-
function normalizeEntrypoint(entrypoint) {
|
|
15
|
-
|
|
16
|
+
function normalizeEntrypoint(entrypoint, root) {
|
|
17
|
+
if (entrypoint instanceof URL) {
|
|
18
|
+
return fileURLToPath(entrypoint);
|
|
19
|
+
}
|
|
20
|
+
if (isRelativePath(entrypoint)) {
|
|
21
|
+
return resolve(fileURLToPath(root), entrypoint);
|
|
22
|
+
}
|
|
23
|
+
return entrypoint;
|
|
16
24
|
}
|
|
17
25
|
export {
|
|
18
26
|
COMPOSE_LOGGER_ENTRYPOINT,
|
|
@@ -60,7 +60,7 @@ function vitePluginLogger({
|
|
|
60
60
|
async handler() {
|
|
61
61
|
const importerPath = fileURLToPath(new URL("package.json", settings.config.root));
|
|
62
62
|
const { expression, imports } = await emitDestination(
|
|
63
|
-
normalizeLoggerConfig(loggerConfig),
|
|
63
|
+
normalizeLoggerConfig(loggerConfig, settings.config.root),
|
|
64
64
|
async (entrypoint) => (await this.resolve(entrypoint, importerPath))?.id ?? null
|
|
65
65
|
);
|
|
66
66
|
return {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type http from 'node:http';
|
|
2
|
+
import type * as vite from 'vite';
|
|
2
3
|
import type { AstroSettings } from '../../types/astro.js';
|
|
3
4
|
import type { AstroLogger } from '../logger/core.js';
|
|
4
5
|
interface PreviewServer {
|
|
5
6
|
host?: string;
|
|
6
7
|
port: number;
|
|
8
|
+
urls?: vite.ResolvedServerUrls;
|
|
7
9
|
server: http.Server;
|
|
8
10
|
closed(): Promise<void>;
|
|
9
11
|
stop(): Promise<void>;
|
|
@@ -73,6 +73,7 @@ async function createStaticPreviewServer(settings, logger) {
|
|
|
73
73
|
return {
|
|
74
74
|
host: getResolvedHostForHttpServer(settings.config.server.host),
|
|
75
75
|
port: actualPort,
|
|
76
|
+
urls: previewServer.resolvedUrls ?? { local: [], network: [] },
|
|
76
77
|
closed,
|
|
77
78
|
server: previewServer.httpServer,
|
|
78
79
|
stop: previewServer.close.bind(previewServer)
|
|
@@ -6,7 +6,7 @@ import { I18n } from "../i18n/handler.js";
|
|
|
6
6
|
import { AstroMiddleware } from "../middleware/astro-middleware.js";
|
|
7
7
|
import { PagesHandler } from "../pages/handler.js";
|
|
8
8
|
import { renderRedirect } from "../redirects/render.js";
|
|
9
|
-
import { provideSession } from "../session/
|
|
9
|
+
import { provideSession } from "../session/provider.js";
|
|
10
10
|
import { prepareResponse } from "../app/prepare-response.js";
|
|
11
11
|
import { ALL_PIPELINE_FEATURES, PipelineFeatures } from "../base-pipeline.js";
|
|
12
12
|
class AstroHandler {
|
|
@@ -3,7 +3,7 @@ export declare const SessionDriverConfigSchema: z.ZodObject<{
|
|
|
3
3
|
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
4
4
|
entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
|
|
5
5
|
}, z.core.$strip>;
|
|
6
|
-
export declare const SessionSchema: z.ZodObject<{
|
|
6
|
+
export declare const SessionSchema: z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
|
|
7
7
|
driver: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
8
8
|
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
9
9
|
entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
|
|
@@ -24,4 +24,4 @@ export declare const SessionSchema: z.ZodObject<{
|
|
|
24
24
|
name: string;
|
|
25
25
|
}, string>>]>>;
|
|
26
26
|
ttl: z.ZodOptional<z.ZodNumber>;
|
|
27
|
-
}, z.core.$strip>;
|
|
27
|
+
}, z.core.$strip>]>;
|