astro 4.11.6 → 4.12.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.
Files changed (100) hide show
  1. package/client.d.ts +1 -0
  2. package/components/Code.astro +12 -0
  3. package/dist/@types/astro.d.ts +154 -74
  4. package/dist/actions/index.d.ts +4 -1
  5. package/dist/actions/index.js +15 -10
  6. package/dist/assets/internal.js +5 -12
  7. package/dist/assets/utils/index.d.ts +2 -1
  8. package/dist/assets/utils/index.js +3 -1
  9. package/dist/assets/utils/{emitAsset.d.ts → node/emitAsset.d.ts} +1 -1
  10. package/dist/assets/utils/{emitAsset.js → node/emitAsset.js} +2 -2
  11. package/dist/assets/utils/remoteProbe.d.ts +2 -2
  12. package/dist/assets/utils/remoteProbe.js +13 -6
  13. package/dist/assets/vite-plugin-assets.js +2 -1
  14. package/dist/cli/check/index.js +7 -5
  15. package/dist/cli/sync/index.d.ts +1 -1
  16. package/dist/cli/sync/index.js +6 -3
  17. package/dist/container/index.js +3 -1
  18. package/dist/content/runtime-assets.js +1 -1
  19. package/dist/content/vite-plugin-content-virtual-mod.js +4 -8
  20. package/dist/core/app/common.js +3 -1
  21. package/dist/core/app/index.js +3 -2
  22. package/dist/core/app/pipeline.d.ts +1 -1
  23. package/dist/core/app/pipeline.js +11 -11
  24. package/dist/core/app/types.d.ts +6 -2
  25. package/dist/core/base-pipeline.d.ts +21 -1
  26. package/dist/core/base-pipeline.js +3 -1
  27. package/dist/core/build/generate.js +1 -0
  28. package/dist/core/build/index.js +10 -6
  29. package/dist/core/build/pipeline.d.ts +6 -0
  30. package/dist/core/build/pipeline.js +11 -8
  31. package/dist/core/build/plugins/plugin-manifest.js +3 -1
  32. package/dist/core/build/plugins/plugin-ssr.js +8 -4
  33. package/dist/core/build/static-build.js +5 -5
  34. package/dist/core/config/schema.d.ts +37 -0
  35. package/dist/core/config/schema.js +5 -2
  36. package/dist/core/config/settings.js +2 -0
  37. package/dist/core/constants.d.ts +7 -0
  38. package/dist/core/constants.js +5 -1
  39. package/dist/core/create-vite.js +2 -2
  40. package/dist/core/dev/container.js +8 -0
  41. package/dist/core/dev/dev.js +1 -1
  42. package/dist/core/errors/dev/vite.js +1 -2
  43. package/dist/core/errors/errors-data.d.ts +2 -10
  44. package/dist/core/errors/errors-data.js +0 -6
  45. package/dist/core/errors/overlay.js +6 -7
  46. package/dist/core/index.d.ts +1 -1
  47. package/dist/core/index.js +1 -1
  48. package/dist/core/messages.js +2 -2
  49. package/dist/core/middleware/callMiddleware.js +6 -6
  50. package/dist/core/redirects/render.js +1 -2
  51. package/dist/core/render/paginate.js +8 -1
  52. package/dist/core/render-context.js +8 -1
  53. package/dist/core/routing/astro-designed-error-pages.d.ts +2 -7
  54. package/dist/core/routing/astro-designed-error-pages.js +4 -1
  55. package/dist/core/routing/default.d.ts +10 -0
  56. package/dist/core/routing/default.js +38 -0
  57. package/dist/core/routing/manifest/create.d.ts +1 -2
  58. package/dist/core/routing/manifest/create.js +2 -34
  59. package/dist/core/routing/manifest/pattern.d.ts +2 -0
  60. package/dist/core/routing/manifest/pattern.js +35 -0
  61. package/dist/core/server-islands/endpoint.d.ts +8 -0
  62. package/dist/core/server-islands/endpoint.js +76 -0
  63. package/dist/core/server-islands/vite-plugin-server-islands.d.ts +7 -0
  64. package/dist/core/server-islands/vite-plugin-server-islands.js +82 -0
  65. package/dist/core/sync/index.d.ts +13 -5
  66. package/dist/core/sync/index.js +36 -23
  67. package/dist/core/sync/setup-env-ts.d.ts +8 -0
  68. package/dist/{vite-plugin-inject-env-ts/index.js → core/sync/setup-env-ts.js} +11 -28
  69. package/dist/env/errors.d.ts +7 -0
  70. package/dist/env/errors.js +16 -0
  71. package/dist/env/runtime.d.ts +4 -3
  72. package/dist/env/runtime.js +9 -5
  73. package/dist/env/validators.d.ts +5 -3
  74. package/dist/env/vite-plugin-env.js +2 -11
  75. package/dist/integrations/hooks.d.ts +3 -1
  76. package/dist/integrations/hooks.js +5 -4
  77. package/dist/jsx/babel.js +6 -8
  78. package/dist/jsx/rehype.js +4 -8
  79. package/dist/jsx-runtime/index.js +1 -2
  80. package/dist/runtime/client/dev-toolbar/entrypoint.js +3 -2
  81. package/dist/runtime/server/render/component.d.ts +2 -1
  82. package/dist/runtime/server/render/component.js +4 -0
  83. package/dist/runtime/server/render/server-islands.d.ts +5 -0
  84. package/dist/runtime/server/render/server-islands.js +73 -0
  85. package/dist/runtime/server/render/slot.d.ts +2 -1
  86. package/dist/runtime/server/render/slot.js +8 -1
  87. package/dist/vite-plugin-astro/index.js +3 -1
  88. package/dist/vite-plugin-astro/metadata.d.ts +1 -0
  89. package/dist/vite-plugin-astro/metadata.js +12 -0
  90. package/dist/vite-plugin-astro/types.d.ts +1 -0
  91. package/dist/vite-plugin-astro-server/pipeline.d.ts +7 -0
  92. package/dist/vite-plugin-astro-server/pipeline.js +20 -5
  93. package/dist/vite-plugin-astro-server/plugin.js +5 -3
  94. package/dist/vite-plugin-astro-server/route.js +13 -14
  95. package/dist/vite-plugin-markdown/index.js +2 -8
  96. package/dist/vite-plugin-utils/index.d.ts +5 -0
  97. package/dist/vite-plugin-utils/index.js +5 -0
  98. package/package.json +5 -4
  99. package/templates/env/module.mjs +5 -2
  100. package/dist/vite-plugin-inject-env-ts/index.d.ts +0 -17
@@ -44,9 +44,12 @@ async function default404Page({ pathname }) {
44
44
  );
45
45
  }
46
46
  default404Page.isAstroComponentFactory = true;
47
+ const default404Instance = {
48
+ default: default404Page
49
+ };
47
50
  export {
48
51
  DEFAULT_404_ROUTE,
49
52
  DEFAULT_500_ROUTE,
50
- default404Page,
53
+ default404Instance,
51
54
  ensure404Route
52
55
  };
@@ -0,0 +1,10 @@
1
+ import type { ComponentInstance, ManifestData, SSRManifest } from '../../@types/astro.js';
2
+ export declare function injectDefaultRoutes(ssrManifest: SSRManifest, routeManifest: ManifestData): ManifestData;
3
+ type DefaultRouteParams = {
4
+ instance: ComponentInstance;
5
+ matchesComponent(filePath: URL): boolean;
6
+ route: string;
7
+ component: string;
8
+ };
9
+ export declare function createDefaultRoutes(manifest: SSRManifest): DefaultRouteParams[];
10
+ export {};
@@ -0,0 +1,38 @@
1
+ import { DEFAULT_404_COMPONENT } from "../constants.js";
2
+ import {
3
+ SERVER_ISLAND_COMPONENT,
4
+ SERVER_ISLAND_ROUTE,
5
+ createEndpoint as createServerIslandEndpoint,
6
+ ensureServerIslandRoute
7
+ } from "../server-islands/endpoint.js";
8
+ import {
9
+ DEFAULT_404_ROUTE,
10
+ default404Instance,
11
+ ensure404Route
12
+ } from "./astro-designed-error-pages.js";
13
+ function injectDefaultRoutes(ssrManifest, routeManifest) {
14
+ ensure404Route(routeManifest);
15
+ ensureServerIslandRoute(ssrManifest, routeManifest);
16
+ return routeManifest;
17
+ }
18
+ function createDefaultRoutes(manifest) {
19
+ const root = new URL(manifest.hrefRoot);
20
+ return [
21
+ {
22
+ instance: default404Instance,
23
+ matchesComponent: (filePath) => filePath.href === new URL(DEFAULT_404_COMPONENT, root).href,
24
+ route: DEFAULT_404_ROUTE.route,
25
+ component: DEFAULT_404_COMPONENT
26
+ },
27
+ {
28
+ instance: createServerIslandEndpoint(manifest),
29
+ matchesComponent: (filePath) => filePath.href === new URL(SERVER_ISLAND_COMPONENT, root).href,
30
+ route: SERVER_ISLAND_ROUTE,
31
+ component: SERVER_ISLAND_COMPONENT
32
+ }
33
+ ];
34
+ }
35
+ export {
36
+ createDefaultRoutes,
37
+ injectDefaultRoutes
38
+ };
@@ -1,8 +1,7 @@
1
- import type { AstroConfig, AstroSettings, ManifestData, RoutePart } from '../../../@types/astro.js';
1
+ import type { AstroSettings, ManifestData, RoutePart } from '../../../@types/astro.js';
2
2
  import type { Logger } from '../../logger/core.js';
3
3
  import nodeFs from 'node:fs';
4
4
  export declare function getParts(part: string, file: string): RoutePart[];
5
- export declare function getPattern(segments: RoutePart[][], base: AstroConfig['base'], addTrailingSlash: AstroConfig['trailingSlash']): RegExp;
6
5
  export declare function validateSegment(segment: string, file?: string): void;
7
6
  export interface CreateRouteManifestParams {
8
7
  /** Astro Settings object */
@@ -12,6 +12,7 @@ import { removeLeadingForwardSlash, slash } from "../../path.js";
12
12
  import { resolvePages } from "../../util.js";
13
13
  import { routeComparator } from "../priority.js";
14
14
  import { getRouteGenerator } from "./generator.js";
15
+ import { getPattern } from "./pattern.js";
15
16
  const require2 = createRequire(import.meta.url);
16
17
  function countOccurrences(needle, haystack) {
17
18
  let count = 0;
@@ -39,38 +40,6 @@ function getParts(part, file) {
39
40
  });
40
41
  return result;
41
42
  }
42
- function getPattern(segments, base, addTrailingSlash) {
43
- const pathname = segments.map((segment) => {
44
- if (segment.length === 1 && segment[0].spread) {
45
- return "(?:\\/(.*?))?";
46
- } else {
47
- return "\\/" + segment.map((part) => {
48
- if (part.spread) {
49
- return "(.*?)";
50
- } else if (part.dynamic) {
51
- return "([^/]+?)";
52
- } else {
53
- return part.content.normalize().replace(/\?/g, "%3F").replace(/#/g, "%23").replace(/%5B/g, "[").replace(/%5D/g, "]").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
54
- }
55
- }).join("");
56
- }
57
- }).join("");
58
- const trailing = addTrailingSlash && segments.length ? getTrailingSlashPattern(addTrailingSlash) : "$";
59
- let initial = "\\/";
60
- if (addTrailingSlash === "never" && base !== "/") {
61
- initial = "";
62
- }
63
- return new RegExp(`^${pathname || initial}${trailing}`);
64
- }
65
- function getTrailingSlashPattern(addTrailingSlash) {
66
- if (addTrailingSlash === "always") {
67
- return "\\/$";
68
- }
69
- if (addTrailingSlash === "never") {
70
- return "$";
71
- }
72
- return "\\/?$";
73
- }
74
43
  function validateSegment(segment, file = "") {
75
44
  if (!file) file = segment;
76
45
  if (/\]\[/.test(segment)) {
@@ -314,7 +283,7 @@ function createRedirectRoutes({ settings }, routeMap, logger) {
314
283
  function isStaticSegment(segment) {
315
284
  return segment.every((part) => !part.dynamic && !part.spread);
316
285
  }
317
- function detectRouteCollision(a, b, config, logger) {
286
+ function detectRouteCollision(a, b, _config, logger) {
318
287
  if (a.type === "fallback" || b.type === "fallback") {
319
288
  return;
320
289
  }
@@ -535,6 +504,5 @@ function joinSegments(segments) {
535
504
  export {
536
505
  createRouteManifest,
537
506
  getParts,
538
- getPattern,
539
507
  validateSegment
540
508
  };
@@ -0,0 +1,2 @@
1
+ import type { AstroConfig, RoutePart } from '../../../@types/astro.js';
2
+ export declare function getPattern(segments: RoutePart[][], base: AstroConfig['base'], addTrailingSlash: AstroConfig['trailingSlash']): RegExp;
@@ -0,0 +1,35 @@
1
+ function getPattern(segments, base, addTrailingSlash) {
2
+ const pathname = segments.map((segment) => {
3
+ if (segment.length === 1 && segment[0].spread) {
4
+ return "(?:\\/(.*?))?";
5
+ } else {
6
+ return "\\/" + segment.map((part) => {
7
+ if (part.spread) {
8
+ return "(.*?)";
9
+ } else if (part.dynamic) {
10
+ return "([^/]+?)";
11
+ } else {
12
+ return part.content.normalize().replace(/\?/g, "%3F").replace(/#/g, "%23").replace(/%5B/g, "[").replace(/%5D/g, "]").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
13
+ }
14
+ }).join("");
15
+ }
16
+ }).join("");
17
+ const trailing = addTrailingSlash && segments.length ? getTrailingSlashPattern(addTrailingSlash) : "$";
18
+ let initial = "\\/";
19
+ if (addTrailingSlash === "never" && base !== "/") {
20
+ initial = "";
21
+ }
22
+ return new RegExp(`^${pathname || initial}${trailing}`);
23
+ }
24
+ function getTrailingSlashPattern(addTrailingSlash) {
25
+ if (addTrailingSlash === "always") {
26
+ return "\\/$";
27
+ }
28
+ if (addTrailingSlash === "never") {
29
+ return "$";
30
+ }
31
+ return "\\/?$";
32
+ }
33
+ export {
34
+ getPattern
35
+ };
@@ -0,0 +1,8 @@
1
+ import type { ComponentInstance, ManifestData, RouteData, SSRManifest } from '../../@types/astro.js';
2
+ export declare const SERVER_ISLAND_ROUTE = "/_server-islands/[name]";
3
+ export declare const SERVER_ISLAND_COMPONENT = "_server-islands.astro";
4
+ type ConfigFields = Pick<SSRManifest, 'base' | 'trailingSlash'>;
5
+ export declare function getServerIslandRouteData(config: ConfigFields): RouteData;
6
+ export declare function ensureServerIslandRoute(config: ConfigFields, routeManifest: ManifestData): void;
7
+ export declare function createEndpoint(manifest: SSRManifest): ComponentInstance;
8
+ export {};
@@ -0,0 +1,76 @@
1
+ import {
2
+ renderComponent,
3
+ renderTemplate
4
+ } from "../../runtime/server/index.js";
5
+ import { createSlotValueFromString } from "../../runtime/server/render/slot.js";
6
+ import { getPattern } from "../routing/manifest/pattern.js";
7
+ const SERVER_ISLAND_ROUTE = "/_server-islands/[name]";
8
+ const SERVER_ISLAND_COMPONENT = "_server-islands.astro";
9
+ function getServerIslandRouteData(config) {
10
+ const segments = [
11
+ [{ content: "_server-islands", dynamic: false, spread: false }],
12
+ [{ content: "name", dynamic: true, spread: false }]
13
+ ];
14
+ const route = {
15
+ type: "page",
16
+ component: SERVER_ISLAND_COMPONENT,
17
+ generate: () => "",
18
+ params: ["name"],
19
+ segments,
20
+ pattern: getPattern(segments, config.base, config.trailingSlash),
21
+ prerender: false,
22
+ isIndex: false,
23
+ fallbackRoutes: [],
24
+ route: SERVER_ISLAND_ROUTE
25
+ };
26
+ return route;
27
+ }
28
+ function ensureServerIslandRoute(config, routeManifest) {
29
+ if (routeManifest.routes.some((route) => route.route === "/_server-islands/[name]")) {
30
+ return;
31
+ }
32
+ routeManifest.routes.push(getServerIslandRouteData(config));
33
+ }
34
+ function createEndpoint(manifest) {
35
+ const page = async (result) => {
36
+ const params = result.params;
37
+ const request = result.request;
38
+ const raw = await request.text();
39
+ const data = JSON.parse(raw);
40
+ if (!params.name) {
41
+ return new Response(null, {
42
+ status: 400,
43
+ statusText: "Bad request"
44
+ });
45
+ }
46
+ const componentId = params.name;
47
+ const imp = manifest.serverIslandMap?.get(componentId);
48
+ if (!imp) {
49
+ return new Response(null, {
50
+ status: 404,
51
+ statusText: "Not found"
52
+ });
53
+ }
54
+ const props = data.props;
55
+ const componentModule = await imp();
56
+ const Component = componentModule[data.componentExport];
57
+ const slots = {};
58
+ for (const prop in data.slots) {
59
+ slots[prop] = createSlotValueFromString(data.slots[prop]);
60
+ }
61
+ return renderTemplate`${renderComponent(result, "Component", Component, props, slots)}`;
62
+ };
63
+ page.isAstroComponentFactory = true;
64
+ const instance = {
65
+ default: page,
66
+ partial: true
67
+ };
68
+ return instance;
69
+ }
70
+ export {
71
+ SERVER_ISLAND_COMPONENT,
72
+ SERVER_ISLAND_ROUTE,
73
+ createEndpoint,
74
+ ensureServerIslandRoute,
75
+ getServerIslandRouteData
76
+ };
@@ -0,0 +1,7 @@
1
+ import type { Plugin as VitePlugin } from 'vite';
2
+ import type { AstroSettings } from '../../@types/astro.js';
3
+ export declare const VIRTUAL_ISLAND_MAP_ID = "@astro-server-islands";
4
+ export declare const RESOLVED_VIRTUAL_ISLAND_MAP_ID: string;
5
+ export declare function vitePluginServerIslands({ settings }: {
6
+ settings: AstroSettings;
7
+ }): VitePlugin;
@@ -0,0 +1,82 @@
1
+ const VIRTUAL_ISLAND_MAP_ID = "@astro-server-islands";
2
+ const RESOLVED_VIRTUAL_ISLAND_MAP_ID = "\0" + VIRTUAL_ISLAND_MAP_ID;
3
+ const serverIslandPlaceholder = "'$$server-islands$$'";
4
+ function vitePluginServerIslands({ settings }) {
5
+ let command = "serve";
6
+ let viteServer = null;
7
+ const referenceIdMap = /* @__PURE__ */ new Map();
8
+ return {
9
+ name: "astro:server-islands",
10
+ enforce: "post",
11
+ config(_config, { command: _command }) {
12
+ command = _command;
13
+ },
14
+ configureServer(_server) {
15
+ viteServer = _server;
16
+ },
17
+ resolveId(name) {
18
+ if (name === VIRTUAL_ISLAND_MAP_ID) {
19
+ return RESOLVED_VIRTUAL_ISLAND_MAP_ID;
20
+ }
21
+ },
22
+ load(id) {
23
+ if (id === RESOLVED_VIRTUAL_ISLAND_MAP_ID) {
24
+ return `export const serverIslandMap = ${serverIslandPlaceholder};`;
25
+ }
26
+ },
27
+ transform(_code, id) {
28
+ if (id.endsWith(".astro")) {
29
+ const info = this.getModuleInfo(id);
30
+ if (info?.meta) {
31
+ const astro = info.meta.astro;
32
+ if (astro?.serverComponents.length) {
33
+ for (const comp of astro.serverComponents) {
34
+ if (!settings.serverIslandNameMap.has(comp.resolvedPath)) {
35
+ let name = comp.localName;
36
+ let idx = 1;
37
+ while (true) {
38
+ if (!settings.serverIslandMap.has(name)) {
39
+ break;
40
+ }
41
+ name += idx++;
42
+ }
43
+ settings.serverIslandNameMap.set(comp.resolvedPath, name);
44
+ settings.serverIslandMap.set(name, () => {
45
+ return viteServer?.ssrLoadModule(comp.resolvedPath);
46
+ });
47
+ if (command === "build") {
48
+ let referenceId = this.emitFile({
49
+ type: "chunk",
50
+ id: comp.specifier,
51
+ importer: id,
52
+ name: comp.localName
53
+ });
54
+ referenceIdMap.set(comp.resolvedPath, referenceId);
55
+ }
56
+ }
57
+ }
58
+ }
59
+ }
60
+ }
61
+ },
62
+ renderChunk(code) {
63
+ if (code.includes(serverIslandPlaceholder)) {
64
+ let mapSource = "new Map([";
65
+ for (let [resolvedPath, referenceId] of referenceIdMap) {
66
+ const fileName = this.getFileName(referenceId);
67
+ const islandName = settings.serverIslandNameMap.get(resolvedPath);
68
+ mapSource += `
69
+ ['${islandName}', () => import('./${fileName}')],`;
70
+ }
71
+ mapSource += "\n]);";
72
+ referenceIdMap.clear();
73
+ return code.replace(serverIslandPlaceholder, mapSource);
74
+ }
75
+ }
76
+ };
77
+ }
78
+ export {
79
+ RESOLVED_VIRTUAL_ISLAND_MAP_ID,
80
+ VIRTUAL_ISLAND_MAP_ID,
81
+ vitePluginServerIslands
82
+ };
@@ -1,14 +1,22 @@
1
- import type { AstroInlineConfig } from '../../@types/astro.js';
1
+ import fsMod from 'node:fs';
2
+ import type { AstroInlineConfig, AstroSettings } from '../../@types/astro.js';
2
3
  import type { Logger } from '../logger/core.js';
3
- export type ProcessExit = 0 | 1;
4
- export type SyncOptions = {};
5
- export type SyncInternalOptions = SyncOptions & {
4
+ export type SyncOptions = {
6
5
  logger: Logger;
6
+ settings: AstroSettings;
7
+ skip?: {
8
+ content?: boolean;
9
+ };
7
10
  };
11
+ export default function sync({ inlineConfig, fs, telemetry: _telemetry, }: {
12
+ inlineConfig: AstroInlineConfig;
13
+ fs?: typeof fsMod;
14
+ telemetry?: boolean;
15
+ }): Promise<void>;
8
16
  /**
9
17
  * Generates TypeScript types for all Astro modules. This sets up a `src/env.d.ts` file for type inferencing,
10
18
  * and defines the `astro:content` module for the Content Collections API.
11
19
  *
12
20
  * @experimental The JavaScript API is experimental
13
21
  */
14
- export default function sync(inlineConfig: AstroInlineConfig, options?: SyncOptions): Promise<ProcessExit>;
22
+ export declare function syncInternal({ logger, fs, settings, skip, }: SyncOptions): Promise<void>;
@@ -10,7 +10,6 @@ import { syncAstroEnv } from "../../env/sync.js";
10
10
  import { telemetry } from "../../events/index.js";
11
11
  import { eventCliSession } from "../../events/session.js";
12
12
  import { runHookConfigSetup } from "../../integrations/hooks.js";
13
- import { setUpEnvTs } from "../../vite-plugin-inject-env-ts/index.js";
14
13
  import { getTimeStat } from "../build/util.js";
15
14
  import { resolveConfig } from "../config/config.js";
16
15
  import { createNodeLogger } from "../config/logging.js";
@@ -26,41 +25,58 @@ import {
26
25
  } from "../errors/index.js";
27
26
  import { formatErrorMessage } from "../messages.js";
28
27
  import { ensureProcessNodeEnv } from "../util.js";
29
- async function sync(inlineConfig, options) {
28
+ import { setUpEnvTs } from "./setup-env-ts.js";
29
+ async function sync({
30
+ inlineConfig,
31
+ fs,
32
+ telemetry: _telemetry = false
33
+ }) {
30
34
  ensureProcessNodeEnv("production");
31
35
  const logger = createNodeLogger(inlineConfig);
32
- const { userConfig, astroConfig } = await resolveConfig(inlineConfig ?? {}, "sync");
33
- telemetry.record(eventCliSession("sync", userConfig));
34
- const _settings = await createSettings(astroConfig, fileURLToPath(astroConfig.root));
35
- const settings = await runHookConfigSetup({
36
- settings: _settings,
37
- logger,
38
- command: "build"
36
+ const { astroConfig, userConfig } = await resolveConfig(inlineConfig ?? {}, "sync");
37
+ if (_telemetry) {
38
+ telemetry.record(eventCliSession("sync", userConfig));
39
+ }
40
+ let settings = await createSettings(astroConfig, inlineConfig.root);
41
+ settings = await runHookConfigSetup({
42
+ command: "build",
43
+ settings,
44
+ logger
39
45
  });
46
+ return await syncInternal({ settings, logger, fs });
47
+ }
48
+ async function syncInternal({
49
+ logger,
50
+ fs = fsMod,
51
+ settings,
52
+ skip
53
+ }) {
54
+ const cwd = fileURLToPath(settings.config.root);
40
55
  const timerStart = performance.now();
41
56
  const dbPackage = await getPackage(
42
57
  "@astrojs/db",
43
58
  logger,
44
59
  {
45
60
  optional: true,
46
- cwd: inlineConfig.root
61
+ cwd
47
62
  },
48
63
  []
49
64
  );
50
65
  try {
51
- await dbPackage?.typegen?.(astroConfig);
52
- const exitCode = await syncContentCollections(settings, { ...options, logger });
53
- if (exitCode !== 0) return exitCode;
54
- syncAstroEnv(settings, options?.fs);
55
- logger.info(null, `Types generated ${dim(getTimeStat(timerStart, performance.now()))}`);
56
- return 0;
66
+ await dbPackage?.typegen?.(settings.config);
67
+ if (!skip?.content) {
68
+ await syncContentCollections(settings, { fs, logger });
69
+ }
70
+ syncAstroEnv(settings, fs);
71
+ await setUpEnvTs({ settings, logger, fs });
72
+ logger.info("types", `Generated ${dim(getTimeStat(timerStart, performance.now()))}`);
57
73
  } catch (err) {
58
74
  const error = createSafeError(err);
59
75
  logger.error(
60
- "content",
76
+ "types",
61
77
  formatErrorMessage(collectErrorMetadata(error), logger.level() === "debug") + "\n"
62
78
  );
63
- return 1;
79
+ throw error;
64
80
  }
65
81
  }
66
82
  async function syncContentCollections(settings, { logger, fs }) {
@@ -86,7 +102,7 @@ async function syncContentCollections(settings, { logger, fs }) {
86
102
  const contentTypesGenerator = await createContentTypesGenerator({
87
103
  contentConfigObserver: globalContentConfigObserver,
88
104
  logger,
89
- fs: fs ?? fsMod,
105
+ fs,
90
106
  settings,
91
107
  viteServer: tempViteServer
92
108
  });
@@ -100,7 +116,6 @@ async function syncContentCollections(settings, { logger, fs }) {
100
116
  case "no-content-dir":
101
117
  default:
102
118
  logger.debug("types", "No content directory found. Skipping type generation.");
103
- return 0;
104
119
  }
105
120
  }
106
121
  } catch (e) {
@@ -120,10 +135,8 @@ async function syncContentCollections(settings, { logger, fs }) {
120
135
  } finally {
121
136
  await tempViteServer.close();
122
137
  }
123
- await setUpEnvTs({ settings, logger, fs: fs ?? fsMod });
124
- return 0;
125
138
  }
126
139
  export {
127
140
  sync as default,
128
- syncContentCollections
141
+ syncInternal
129
142
  };
@@ -0,0 +1,8 @@
1
+ import type fsMod from 'node:fs';
2
+ import type { AstroSettings } from '../../@types/astro.js';
3
+ import { type Logger } from '../logger/core.js';
4
+ export declare function setUpEnvTs({ settings, logger, fs, }: {
5
+ settings: AstroSettings;
6
+ logger: Logger;
7
+ fs: typeof fsMod;
8
+ }): Promise<void>;
@@ -2,28 +2,10 @@ import path from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { bold } from "kleur/colors";
4
4
  import { normalizePath } from "vite";
5
- import { ACTIONS_TYPES_FILE } from "../actions/consts.js";
6
- import { CONTENT_TYPES_FILE } from "../content/consts.js";
7
- import {} from "../core/logger/core.js";
8
- import { ENV_TYPES_FILE } from "../env/constants.js";
9
- function getEnvTsPath({ srcDir }) {
10
- return new URL("env.d.ts", srcDir);
11
- }
12
- function astroInjectEnvTsPlugin({
13
- settings,
14
- logger,
15
- fs
16
- }) {
17
- return {
18
- name: "astro-inject-env-ts",
19
- // Use `post` to ensure project setup is complete
20
- // Ex. `.astro` types have been written
21
- enforce: "post",
22
- async config() {
23
- await setUpEnvTs({ settings, logger, fs });
24
- }
25
- };
26
- }
5
+ import { ACTIONS_TYPES_FILE } from "../../actions/consts.js";
6
+ import { CONTENT_TYPES_FILE } from "../../content/consts.js";
7
+ import { ENV_TYPES_FILE } from "../../env/constants.js";
8
+ import {} from "../logger/core.js";
27
9
  function getDotAstroTypeReference({
28
10
  settings,
29
11
  filename
@@ -41,7 +23,7 @@ async function setUpEnvTs({
41
23
  logger,
42
24
  fs
43
25
  }) {
44
- const envTsPath = getEnvTsPath(settings.config);
26
+ const envTsPath = new URL("env.d.ts", settings.config.srcDir);
45
27
  const envTsPathRelativetoRoot = normalizePath(
46
28
  path.relative(fileURLToPath(settings.config.root), fileURLToPath(envTsPath))
47
29
  );
@@ -61,7 +43,8 @@ async function setUpEnvTs({
61
43
  });
62
44
  }
63
45
  if (fs.existsSync(envTsPath)) {
64
- let typesEnvContents = await fs.promises.readFile(envTsPath, "utf-8");
46
+ const initialEnvContents = await fs.promises.readFile(envTsPath, "utf-8");
47
+ let typesEnvContents = initialEnvContents;
65
48
  for (const injectedType of injectedTypes) {
66
49
  if (!injectedType.meetsCondition || await injectedType.meetsCondition?.()) {
67
50
  const expectedTypeReference = getDotAstroTypeReference({
@@ -74,8 +57,10 @@ ${typesEnvContents}`;
74
57
  }
75
58
  }
76
59
  }
77
- logger.info("types", `Added ${bold(envTsPathRelativetoRoot)} type declarations.`);
78
- await fs.promises.writeFile(envTsPath, typesEnvContents, "utf-8");
60
+ if (initialEnvContents !== typesEnvContents) {
61
+ logger.info("types", `Updated ${bold(envTsPathRelativetoRoot)} type declarations.`);
62
+ await fs.promises.writeFile(envTsPath, typesEnvContents, "utf-8");
63
+ }
79
64
  } else {
80
65
  let referenceDefs = [];
81
66
  referenceDefs.push('/// <reference types="astro/client" />');
@@ -90,7 +75,5 @@ ${typesEnvContents}`;
90
75
  }
91
76
  }
92
77
  export {
93
- astroInjectEnvTsPlugin,
94
- getEnvTsPath,
95
78
  setUpEnvTs
96
79
  };
@@ -0,0 +1,7 @@
1
+ import type { ValidationResultErrors } from './validators.js';
2
+ export interface InvalidVariable {
3
+ key: string;
4
+ type: string;
5
+ errors: ValidationResultErrors;
6
+ }
7
+ export declare function invalidVariablesToError(invalid: Array<InvalidVariable>): string[];
@@ -0,0 +1,16 @@
1
+ function invalidVariablesToError(invalid) {
2
+ const _errors = [];
3
+ for (const { key, type, errors } of invalid) {
4
+ if (errors[0] === "missing") {
5
+ _errors.push(`${key} is missing`);
6
+ } else if (errors[0] === "type") {
7
+ _errors.push(`${key}'s type is invalid, expected: ${type}`);
8
+ } else {
9
+ _errors.push(`The following constraints for ${key} are not met: ${errors.join(", ")}`);
10
+ }
11
+ }
12
+ return _errors;
13
+ }
14
+ export {
15
+ invalidVariablesToError
16
+ };
@@ -1,8 +1,9 @@
1
- import { AstroError, AstroErrorData } from '../core/errors/index.js';
2
- export { validateEnvVariable } from './validators.js';
1
+ import { AstroError } from '../core/errors/index.js';
2
+ import type { ValidationResultInvalid } from './validators.js';
3
+ export { validateEnvVariable, getEnvFieldType } from './validators.js';
3
4
  export type GetEnv = (key: string) => string | undefined;
4
5
  export declare function setGetEnv(fn: GetEnv, reset?: boolean): void;
5
6
  declare let _onSetGetEnv: (reset: boolean) => void;
6
7
  export declare function setOnSetGetEnv(fn: typeof _onSetGetEnv): void;
7
8
  export declare function getEnv(...args: Parameters<GetEnv>): string | undefined;
8
- export declare function createInvalidVariableError(...args: Parameters<typeof AstroErrorData.EnvInvalidVariable.message>): AstroError;
9
+ export declare function createInvalidVariablesError(key: string, type: string, result: ValidationResultInvalid): AstroError;
@@ -1,5 +1,6 @@
1
1
  import { AstroError, AstroErrorData } from "../core/errors/index.js";
2
- import { validateEnvVariable } from "./validators.js";
2
+ import { invalidVariablesToError } from "./errors.js";
3
+ import { validateEnvVariable, getEnvFieldType } from "./validators.js";
3
4
  let _getEnv = (key) => process.env[key];
4
5
  function setGetEnv(fn, reset = false) {
5
6
  _getEnv = fn;
@@ -13,15 +14,18 @@ function setOnSetGetEnv(fn) {
13
14
  function getEnv(...args) {
14
15
  return _getEnv(...args);
15
16
  }
16
- function createInvalidVariableError(...args) {
17
+ function createInvalidVariablesError(key, type, result) {
17
18
  return new AstroError({
18
- ...AstroErrorData.EnvInvalidVariable,
19
- message: AstroErrorData.EnvInvalidVariable.message(...args)
19
+ ...AstroErrorData.EnvInvalidVariables,
20
+ message: AstroErrorData.EnvInvalidVariables.message(
21
+ invalidVariablesToError([{ key, type, errors: result.errors }])
22
+ )
20
23
  });
21
24
  }
22
25
  export {
23
- createInvalidVariableError,
26
+ createInvalidVariablesError,
24
27
  getEnv,
28
+ getEnvFieldType,
25
29
  setGetEnv,
26
30
  setOnSetGetEnv,
27
31
  validateEnvVariable
@@ -1,13 +1,15 @@
1
1
  import type { EnvFieldType } from './schema.js';
2
2
  export type ValidationResultValue = EnvFieldType['default'];
3
3
  export type ValidationResultErrors = ['missing'] | ['type'] | Array<string>;
4
- type ValidationResult = {
4
+ interface ValidationResultValid {
5
5
  ok: true;
6
6
  value: ValidationResultValue;
7
- } | {
7
+ }
8
+ export interface ValidationResultInvalid {
8
9
  ok: false;
9
10
  errors: ValidationResultErrors;
10
- };
11
+ }
12
+ type ValidationResult = ValidationResultValid | ValidationResultInvalid;
11
13
  export declare function getEnvFieldType(options: EnvFieldType): string;
12
14
  export declare function validateEnvVariable(value: string | undefined, options: EnvFieldType): ValidationResult;
13
15
  export {};