Skip to content

Commit 76ddef1

Browse files
Princesseuhematipico
authored andcommitted
feat: remove automatic flattening of getStaticPaths result (#7845)
* feat: remove automatic flattening of `getStaticPaths` result * chore: changeset
1 parent 3dc1ca2 commit 76ddef1

12 files changed

Lines changed: 42 additions & 62 deletions

File tree

.changeset/chilled-ducks-grin.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'astro': major
3+
---
4+
5+
Removed automatic flattening of `getStaticPaths` result. `.flatMap` and `.flat` should now be used to ensure that you're returning a flat array.

packages/astro/src/@types/astro.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,10 +1525,7 @@ export type GetStaticPathsResultKeyed = GetStaticPathsResult & {
15251525
*/
15261526
export type GetStaticPaths = (
15271527
options: GetStaticPathsOptions
1528-
) =>
1529-
| Promise<GetStaticPathsResult | GetStaticPathsResult[]>
1530-
| GetStaticPathsResult
1531-
| GetStaticPathsResult[];
1528+
) => Promise<GetStaticPathsResult> | GetStaticPathsResult;
15321529

15331530
/**
15341531
* Infers the shape of the `params` property returned by `getStaticPaths()`.

packages/astro/src/core/build/generate.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,6 @@ async function getPathsForRoute(
300300
mod,
301301
route,
302302
routeCache: opts.routeCache,
303-
isValidate: false,
304303
logging: opts.logging,
305304
ssr: isServerLikeOutput(opts.settings.config),
306305
}).catch((err) => {

packages/astro/src/core/errors/errors-data.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,28 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon
231231
`Invalid params given to \`getStaticPaths\` path. Expected an \`object\`, got \`${paramType}\``,
232232
hint: 'See https://docs.astro.build/en/reference/api-reference/#getstaticpaths for more information on getStaticPaths.',
233233
},
234+
/**
235+
* @docs
236+
* @see
237+
* - [`getStaticPaths()`](https://docs.astro.build/en/reference/api-reference/#getstaticpaths)
238+
* @description
239+
* `getStaticPaths`'s return value must be an array of objects. In most cases, this error happens because an array of array was returned. Using [`.flatMap()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap) or a [`.flat()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat) call may be useful.
240+
*
241+
* ```ts title="pages/blog/[id].astro"
242+
* export async function getStaticPaths() {
243+
* return [ // <-- Array
244+
* { params: { slug: "blog" } }, // <-- Object
245+
* { params: { slug: "about" } }
246+
* ];
247+
*}
248+
* ```
249+
*/
250+
InvalidGetStaticPathsEntry: {
251+
title: "Invalid entry inside getStaticPath's return value",
252+
message: (entryType) =>
253+
`Invalid entry returned by getStaticPaths. Expected an object, got \`${entryType}\``,
254+
hint: "If you're using a `.map` call, you might be looking for `.flatMap()` instead. See https://docs.astro.build/en/reference/api-reference/#getstaticpaths for more information on getStaticPaths.",
255+
},
234256
/**
235257
* @docs
236258
* @see
@@ -254,6 +276,7 @@ but ${plural ? 'none were' : 'it was not'} able to server-side render \`${compon
254276
`Invalid type returned by \`getStaticPaths\`. Expected an \`array\`, got \`${returnType}\``,
255277
hint: 'See https://docs.astro.build/en/reference/api-reference/#getstaticpaths for more information on getStaticPaths.',
256278
},
279+
257280
/**
258281
* @docs
259282
* @see

packages/astro/src/core/render/params-and-props.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ export async function getParamsAndProps(opts: GetParamsAndPropsOptions): Promise
3333
mod,
3434
route,
3535
routeCache,
36-
isValidate: true,
3736
logging,
3837
ssr,
3938
});

packages/astro/src/core/render/route-cache.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ interface CallGetStaticPathsOptions {
1818
mod: ComponentInstance;
1919
route: RouteData;
2020
routeCache: RouteCache;
21-
isValidate: boolean;
2221
logging: LogOptions;
2322
ssr: boolean;
2423
}
@@ -27,7 +26,6 @@ export async function callGetStaticPaths({
2726
mod,
2827
route,
2928
routeCache,
30-
isValidate,
3129
logging,
3230
ssr,
3331
}: CallGetStaticPathsOptions): Promise<GetStaticPathsResultKeyed> {
@@ -58,14 +56,7 @@ export async function callGetStaticPaths({
5856
},
5957
});
6058

61-
// Flatten the array before validating the content, otherwise users using `.map` will run into errors
62-
if (Array.isArray(staticPaths)) {
63-
staticPaths = staticPaths.flat();
64-
}
65-
66-
if (isValidate) {
67-
validateGetStaticPathsResult(staticPaths, logging, route);
68-
}
59+
validateGetStaticPathsResult(staticPaths, logging, route);
6960

7061
const keyedStaticPaths = staticPaths as GetStaticPathsResultKeyed;
7162
keyedStaticPaths.keyed = new Map<string, GetStaticPathsItem>();

packages/astro/src/core/routing/validation.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ export function validateGetStaticPathsResult(
5454
}
5555

5656
result.forEach((pathObject) => {
57+
if ((typeof pathObject === 'object' && Array.isArray(pathObject)) || pathObject === null) {
58+
throw new AstroError({
59+
...AstroErrorData.InvalidGetStaticPathsEntry,
60+
message: AstroErrorData.InvalidGetStaticPathsEntry.message(
61+
Array.isArray(pathObject) ? 'array' : typeof pathObject
62+
),
63+
});
64+
}
65+
5766
if (
5867
pathObject.params === undefined ||
5968
pathObject.params === null ||
@@ -67,16 +76,6 @@ export function validateGetStaticPathsResult(
6776
});
6877
}
6978

70-
if (typeof pathObject.params !== 'object') {
71-
throw new AstroError({
72-
...AstroErrorData.InvalidGetStaticPathParam,
73-
message: AstroErrorData.InvalidGetStaticPathParam.message(typeof pathObject.params),
74-
location: {
75-
file: route.component,
76-
},
77-
});
78-
}
79-
8079
// TODO: Replace those with errors? They technically don't crash the build, but users might miss the warning. - erika, 2022-11-07
8180
for (const [key, val] of Object.entries(pathObject.params)) {
8281
if (!(typeof val === 'undefined' || typeof val === 'string' || typeof val === 'number')) {

packages/astro/test/astro-get-static-paths.test.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { expect } from 'chai';
2-
import { loadFixture } from './test-utils.js';
32
import * as cheerio from 'cheerio';
3+
import { loadFixture } from './test-utils.js';
44

55
describe('getStaticPaths - build calls', () => {
66
/** @type {import('./test-utils').Fixture} */
@@ -92,11 +92,6 @@ describe('getStaticPaths - dev calls', () => {
9292
});
9393

9494
describe('route params type validation', () => {
95-
it('resolves 200 on nested array parameters', async () => {
96-
const res = await fixture.fetch('/nested-arrays/slug1');
97-
expect(res.status).to.equal(200);
98-
});
99-
10095
it('resolves 200 on matching static path - string params', async () => {
10196
// route provided with { params: { year: "2022", slug: "post-2" }}
10297
const res = await fixture.fetch('/blog/2022/post-1');

packages/astro/test/fixtures/astro-get-static-paths/src/pages/nested-arrays/[slug].astro

Lines changed: 0 additions & 8 deletions
This file was deleted.

packages/astro/test/fixtures/astro-pagination/src/pages/posts/[slug]/[page].astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
export async function getStaticPaths({paginate}) {
33
const allPosts = await Astro.glob('../../post/*.md');
4-
return ['red', 'blue'].map((filter) => {
4+
return ['red', 'blue'].flatMap((filter) => {
55
const filteredPosts = allPosts.filter((post) => post.frontmatter.tag === filter);
66
return paginate(filteredPosts, {
77
params: { slug: filter },

0 commit comments

Comments
 (0)