astro 1.0.0-beta.45 → 1.0.0-beta.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -40,7 +40,7 @@ function printAstroHelp() {
40
40
  });
41
41
  }
42
42
  async function printVersion() {
43
- const version = "1.0.0-beta.45";
43
+ const version = "1.0.0-beta.46";
44
44
  console.log();
45
45
  console.log(` ${colors.bgGreen(colors.black(` astro `))} ${colors.green(`v${version}`)}`);
46
46
  }
@@ -83,7 +83,7 @@ async function cli(args) {
83
83
  } else if (flags.silent) {
84
84
  logging.level = "silent";
85
85
  }
86
- const telemetry = new AstroTelemetry({ version: "1.0.0-beta.45" });
86
+ const telemetry = new AstroTelemetry({ version: "1.0.0-beta.46" });
87
87
  if (cmd === "telemetry") {
88
88
  try {
89
89
  const subcommand = (_a = flags._[3]) == null ? void 0 : _a.toString();
@@ -97,7 +97,7 @@ async function cli(args) {
97
97
  try {
98
98
  const packages = flags._.slice(3);
99
99
  telemetry.record(event.eventCliSession({
100
- astroVersion: "1.0.0-beta.45",
100
+ astroVersion: "1.0.0-beta.46",
101
101
  cliCommand: "add"
102
102
  }));
103
103
  return await add(packages, { cwd: root, flags, logging, telemetry });
@@ -108,7 +108,7 @@ async function cli(args) {
108
108
  case "dev": {
109
109
  try {
110
110
  const { astroConfig, userConfig } = await openConfig({ cwd: root, flags, cmd });
111
- telemetry.record(event.eventCliSession({ astroVersion: "1.0.0-beta.45", cliCommand: "dev" }, userConfig, flags));
111
+ telemetry.record(event.eventCliSession({ astroVersion: "1.0.0-beta.46", cliCommand: "dev" }, userConfig, flags));
112
112
  await devServer(astroConfig, { logging, telemetry });
113
113
  return await new Promise(() => {
114
114
  });
@@ -119,7 +119,7 @@ async function cli(args) {
119
119
  case "build": {
120
120
  try {
121
121
  const { astroConfig, userConfig } = await openConfig({ cwd: root, flags, cmd });
122
- telemetry.record(event.eventCliSession({ astroVersion: "1.0.0-beta.45", cliCommand: "build" }, userConfig, flags));
122
+ telemetry.record(event.eventCliSession({ astroVersion: "1.0.0-beta.46", cliCommand: "build" }, userConfig, flags));
123
123
  return await build(astroConfig, { logging, telemetry });
124
124
  } catch (err) {
125
125
  return throwAndExit(err);
@@ -127,14 +127,14 @@ async function cli(args) {
127
127
  }
128
128
  case "check": {
129
129
  const { astroConfig, userConfig } = await openConfig({ cwd: root, flags, cmd });
130
- telemetry.record(event.eventCliSession({ astroVersion: "1.0.0-beta.45", cliCommand: "check" }, userConfig, flags));
130
+ telemetry.record(event.eventCliSession({ astroVersion: "1.0.0-beta.46", cliCommand: "check" }, userConfig, flags));
131
131
  const ret = await check(astroConfig);
132
132
  return process.exit(ret);
133
133
  }
134
134
  case "preview": {
135
135
  try {
136
136
  const { astroConfig, userConfig } = await openConfig({ cwd: root, flags, cmd });
137
- telemetry.record(event.eventCliSession({ astroVersion: "1.0.0-beta.45", cliCommand: "preview" }, userConfig, flags));
137
+ telemetry.record(event.eventCliSession({ astroVersion: "1.0.0-beta.46", cliCommand: "preview" }, userConfig, flags));
138
138
  const server = await preview(astroConfig, { logging, telemetry });
139
139
  return await server.closed();
140
140
  } catch (err) {
@@ -144,7 +144,7 @@ async function cli(args) {
144
144
  case "docs": {
145
145
  try {
146
146
  await telemetry.record(event.eventCliSession({
147
- astroVersion: "1.0.0-beta.45",
147
+ astroVersion: "1.0.0-beta.46",
148
148
  cliCommand: "docs"
149
149
  }));
150
150
  return await openInBrowser("https://docs.astro.build/");
@@ -33,7 +33,7 @@ class AstroBuilder {
33
33
  this.logging = options.logging;
34
34
  this.routeCache = new RouteCache(this.logging);
35
35
  this.origin = config.site ? new URL(config.site).origin : `http://localhost:${config.server.port}`;
36
- this.manifest = createRouteManifest({ config }, this.logging);
36
+ this.manifest = { routes: [] };
37
37
  this.timer = {};
38
38
  }
39
39
  async setup() {
@@ -42,6 +42,7 @@ class AstroBuilder {
42
42
  this.timer.init = performance.now();
43
43
  this.timer.viteStart = performance.now();
44
44
  this.config = await runHookConfigSetup({ config: this.config, command: "build" });
45
+ this.manifest = createRouteManifest({ config: this.config }, this.logging);
45
46
  const viteConfig = await createVite({
46
47
  mode: this.mode,
47
48
  server: {
@@ -205,7 +205,7 @@ See https://astro.build/config for more information.`);
205
205
  }).optional().default({})
206
206
  });
207
207
  const result = __spreadProps(__spreadValues({}, await AstroConfigRelativeSchema.parseAsync(userConfig)), {
208
- _ctx: { scripts: [], renderers: [], adapter: void 0 }
208
+ _ctx: { scripts: [], renderers: [], injectedRoutes: [], adapter: void 0 }
209
209
  });
210
210
  if (!((_a = result.experimental) == null ? void 0 : _a.integrations) && !result.integrations.every((int) => int.name.startsWith("@astrojs/"))) {
211
211
  throw new Error([
@@ -47,7 +47,7 @@ async function dev(config, options) {
47
47
  site,
48
48
  https: !!((_a = viteConfig.server) == null ? void 0 : _a.https)
49
49
  }));
50
- const currentVersion = "1.0.0-beta.45";
50
+ const currentVersion = "1.0.0-beta.46";
51
51
  if (currentVersion.includes("-")) {
52
52
  warn(options.logging, null, msg.prerelease({ currentVersion }));
53
53
  }
@@ -47,7 +47,7 @@ function devStart({
47
47
  https,
48
48
  site
49
49
  }) {
50
- const version = "1.0.0-beta.45";
50
+ const version = "1.0.0-beta.46";
51
51
  const rootPath = site ? site.pathname : "/";
52
52
  const localPrefix = `${dim("\u2503")} Local `;
53
53
  const networkPrefix = `${dim("\u2503")} Network `;
@@ -207,7 +207,7 @@ function printHelp({
207
207
  };
208
208
  let message = [];
209
209
  if (headline) {
210
- message.push(linebreak(), ` ${bgGreen(black(` ${commandName} `))} ${green(`v${"1.0.0-beta.45"}`)} ${headline}`);
210
+ message.push(linebreak(), ` ${bgGreen(black(` ${commandName} `))} ${green(`v${"1.0.0-beta.46"}`)} ${headline}`);
211
211
  }
212
212
  if (usage) {
213
213
  message.push(linebreak(), ` ${green(commandName)} ${bold(usage)}`);
@@ -1,10 +1,12 @@
1
1
  import fs from "fs";
2
+ import { createRequire } from "module";
2
3
  import path from "path";
3
4
  import slash from "slash";
4
5
  import { fileURLToPath } from "url";
5
6
  import { warn } from "../../logger/core.js";
6
7
  import { resolvePages } from "../../util.js";
7
8
  import { getRouteGenerator } from "./generator.js";
9
+ const require2 = createRequire(import.meta.url);
8
10
  function countOccurrences(needle, haystack) {
9
11
  let count = 0;
10
12
  for (let i = 0; i < haystack.length; i += 1) {
@@ -54,6 +56,22 @@ function isSpread(str) {
54
56
  const spreadPattern = /\[\.{3}/g;
55
57
  return spreadPattern.test(str);
56
58
  }
59
+ function validateSegment(segment, file = "") {
60
+ if (!file)
61
+ file = segment;
62
+ if (/^\$/.test(segment)) {
63
+ throw new Error(`Invalid route ${file} \u2014 Astro's Collections API has been replaced by dynamic route params.`);
64
+ }
65
+ if (/\]\[/.test(segment)) {
66
+ throw new Error(`Invalid route ${file} \u2014 parameters must be separated`);
67
+ }
68
+ if (countOccurrences("[", segment) !== countOccurrences("]", segment)) {
69
+ throw new Error(`Invalid route ${file} \u2014 brackets are unbalanced`);
70
+ }
71
+ if (/.+\[\.\.\.[^\]]+\]/.test(segment) || /\[\.\.\.[^\]]+\].+/.test(segment)) {
72
+ throw new Error(`Invalid route ${file} \u2014 rest parameter must be a standalone segment`);
73
+ }
74
+ }
57
75
  function comparator(a, b) {
58
76
  if (a.isIndex !== b.isIndex) {
59
77
  if (a.isIndex)
@@ -86,6 +104,7 @@ function comparator(a, b) {
86
104
  return a.file < b.file ? -1 : 1;
87
105
  }
88
106
  function createRouteManifest({ config, cwd }, logging) {
107
+ var _a, _b, _c, _d;
89
108
  const components = [];
90
109
  const routes = [];
91
110
  const validPageExtensions = /* @__PURE__ */ new Set([".astro", ".md"]);
@@ -108,18 +127,7 @@ function createRouteManifest({ config, cwd }, logging) {
108
127
  return;
109
128
  }
110
129
  const segment = isDir ? basename : name;
111
- if (/^\$/.test(segment)) {
112
- throw new Error(`Invalid route ${file} \u2014 Astro's Collections API has been replaced by dynamic route params.`);
113
- }
114
- if (/\]\[/.test(segment)) {
115
- throw new Error(`Invalid route ${file} \u2014 parameters must be separated`);
116
- }
117
- if (countOccurrences("[", segment) !== countOccurrences("]", segment)) {
118
- throw new Error(`Invalid route ${file} \u2014 brackets are unbalanced`);
119
- }
120
- if (/.+\[\.\.\.[^\]]+\]/.test(segment) || /\[\.\.\.[^\]]+\].+/.test(segment)) {
121
- throw new Error(`Invalid route ${file} \u2014 rest parameter must be a standalone segment`);
122
- }
130
+ validateSegment(segment, file);
123
131
  const parts = getParts(segment, file);
124
132
  const isIndex = isDir ? false : basename.startsWith("index.");
125
133
  const routeSuffix = basename.slice(basename.indexOf("."), -ext.length);
@@ -175,7 +183,9 @@ function createRouteManifest({ config, cwd }, logging) {
175
183
  const pattern = getPattern(segments, trailingSlash);
176
184
  const generate = getRouteGenerator(segments, trailingSlash);
177
185
  const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic) ? `/${segments.map((segment) => segment[0].content).join("/")}` : null;
186
+ const route = `/${segments.map(([{ dynamic, content }]) => dynamic ? `[${content}]` : content).join("/")}`.toLowerCase();
178
187
  routes.push({
188
+ route,
179
189
  type: item.isPage ? "page" : "endpoint",
180
190
  pattern,
181
191
  segments,
@@ -190,10 +200,51 @@ function createRouteManifest({ config, cwd }, logging) {
190
200
  const pages = resolvePages(config);
191
201
  if (fs.existsSync(pages)) {
192
202
  walk(fileURLToPath(pages), [], []);
193
- } else {
203
+ } else if (((_b = (_a = config == null ? void 0 : config._ctx) == null ? void 0 : _a.injectedRoutes) == null ? void 0 : _b.length) === 0) {
194
204
  const pagesDirRootRelative = pages.href.slice(config.root.href.length);
195
205
  warn(logging, "astro", `Missing pages directory: ${pagesDirRootRelative}`);
196
206
  }
207
+ (_d = (_c = config == null ? void 0 : config._ctx) == null ? void 0 : _c.injectedRoutes) == null ? void 0 : _d.forEach(({ pattern: name, entryPoint }) => {
208
+ const resolved = require2.resolve(entryPoint, { paths: [cwd || fileURLToPath(config.root)] });
209
+ const component = slash(path.relative(cwd || fileURLToPath(config.root), resolved));
210
+ const isDynamic = (str) => (str == null ? void 0 : str[0]) === "[";
211
+ const normalize = (str) => str == null ? void 0 : str.substring(1, (str == null ? void 0 : str.length) - 1);
212
+ const segments = name.split(path.sep).filter(Boolean).map((s) => {
213
+ validateSegment(s);
214
+ const dynamic = isDynamic(s);
215
+ const content = dynamic ? normalize(s) : s;
216
+ return [
217
+ {
218
+ content,
219
+ dynamic,
220
+ spread: isSpread(s)
221
+ }
222
+ ];
223
+ });
224
+ const type = resolved.endsWith(".astro") ? "page" : "endpoint";
225
+ const isPage = type === "page";
226
+ const trailingSlash = isPage ? config.trailingSlash : "never";
227
+ const pattern = getPattern(segments, trailingSlash);
228
+ const generate = getRouteGenerator(segments, trailingSlash);
229
+ const pathname = segments.every((segment) => segment.length === 1 && !segment[0].dynamic) ? `/${segments.map((segment) => segment[0].content).join("/")}` : null;
230
+ const params = segments.flat().filter((p) => p.dynamic).map((p) => p.content);
231
+ const route = `/${segments.map(([{ dynamic, content }]) => dynamic ? `[${content}]` : content).join("/")}`.toLowerCase();
232
+ const collision = routes.find(({ route: r }) => r === route);
233
+ if (collision) {
234
+ throw new Error(`An integration attempted to inject a route that is already used in your project: "${route}" at "${component}".
235
+ This route collides with: "${collision.component}".`);
236
+ }
237
+ routes.push({
238
+ type,
239
+ route,
240
+ pattern,
241
+ segments,
242
+ params,
243
+ component,
244
+ generate,
245
+ pathname: pathname || void 0
246
+ });
247
+ });
197
248
  return {
198
249
  routes
199
250
  };
@@ -27,6 +27,7 @@ function serializeRouteData(routeData, trailingSlash) {
27
27
  }
28
28
  function deserializeRouteData(rawRouteData) {
29
29
  return {
30
+ route: rawRouteData.route,
30
31
  type: rawRouteData.type,
31
32
  pattern: new RegExp(rawRouteData.pattern),
32
33
  params: rawRouteData.params,
@@ -39,6 +39,9 @@ async function runHookConfigSetup({
39
39
  },
40
40
  updateConfig: (newConfig) => {
41
41
  updatedConfig = mergeConfig(updatedConfig, newConfig);
42
+ },
43
+ injectRoute: (injectRoute) => {
44
+ updatedConfig._ctx.injectedRoutes.push(injectRoute);
42
45
  }
43
46
  });
44
47
  }
@@ -655,10 +655,15 @@ export declare type InjectedScriptStage = 'before-hydration' | 'head-inline' | '
655
655
  * Resolved Astro Config
656
656
  * Config with user settings along with all defaults filled in.
657
657
  */
658
+ export interface InjectedRoute {
659
+ pattern: string;
660
+ entryPoint: string;
661
+ }
658
662
  export interface AstroConfig extends z.output<typeof AstroConfigSchema> {
659
663
  integrations: AstroIntegration[];
660
664
  adapter?: AstroIntegration;
661
665
  _ctx: {
666
+ injectedRoutes: InjectedRoute[];
662
667
  adapter: AstroAdapter | undefined;
663
668
  renderers: AstroRenderer[];
664
669
  scripts: {
@@ -692,7 +697,7 @@ export interface MarkdownInstance<T extends Record<string, any>> {
692
697
  getHeaders(): Promise<MarkdownHeader[]>;
693
698
  default: () => Promise<{
694
699
  metadata: MarkdownMetadata;
695
- frontmatter: MarkdownContent;
700
+ frontmatter: MarkdownContent<T>;
696
701
  $$metadata: Metadata;
697
702
  default: AstroComponentFactory;
698
703
  }>;
@@ -738,10 +743,9 @@ export interface MarkdownParserResponse extends MarkdownRenderingResult {
738
743
  * The `content` prop given to a Layout
739
744
  * https://docs.astro.build/guides/markdown-content/#markdown-layouts
740
745
  */
741
- export interface MarkdownContent {
742
- [key: string]: any;
746
+ export declare type MarkdownContent<T extends Record<string, any> = Record<string, any>> = T & {
743
747
  astro: MarkdownMetadata;
744
- }
748
+ };
745
749
  /**
746
750
  * paginate() Options
747
751
  * Docs: https://docs.astro.build/guides/pagination/#calling-the-paginate-function
@@ -835,6 +839,7 @@ export interface AstroIntegration {
835
839
  updateConfig: (newConfig: Record<string, any>) => void;
836
840
  addRenderer: (renderer: AstroRenderer) => void;
837
841
  injectScript: (stage: InjectedScriptStage, content: string) => void;
842
+ injectRoute: (injectRoute: InjectedRoute) => void;
838
843
  }) => void;
839
844
  'astro:config:done'?: (options: {
840
845
  config: AstroConfig;
@@ -875,6 +880,7 @@ export interface RoutePart {
875
880
  spread: boolean;
876
881
  }
877
882
  export interface RouteData {
883
+ route: string;
878
884
  component: string;
879
885
  generate: (data?: any) => string;
880
886
  params: string[];
@@ -116,7 +116,7 @@ function rollupPluginAstroBuildCSS(options) {
116
116
  fileName: imp,
117
117
  name: imp,
118
118
  facadeModuleId: imp,
119
- code: `/* Pure CSS chunk ${imp} */ ${bindings.map((b) => `export const ${b} = {};`)}`,
119
+ code: `/* Pure CSS chunk ${imp} */ ${bindings.map((b) => `export const ${b} = {};`).join("")}`,
120
120
  dynamicImports: [],
121
121
  implicitlyLoadedBefore: [],
122
122
  importedBindings: {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "1.0.0-beta.45",
3
+ "version": "1.0.0-beta.46",
4
4
  "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
5
5
  "type": "module",
6
6
  "author": "withastro",