summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/few-ways-jump.md5
-rw-r--r--packages/astro/src/@types/astro.ts2
-rw-r--r--packages/astro/src/core/render/route-cache.ts6
-rw-r--r--packages/astro/src/core/routing/params.ts23
-rw-r--r--packages/astro/src/core/routing/validation.ts11
-rw-r--r--packages/astro/test/astro-get-static-paths.test.js22
-rw-r--r--packages/astro/test/fixtures/astro-get-static-paths/src/pages/blog/[year]/[slug].astro1
7 files changed, 64 insertions, 6 deletions
diff --git a/.changeset/few-ways-jump.md b/.changeset/few-ways-jump.md
new file mode 100644
index 000000000..7f046d263
--- /dev/null
+++ b/.changeset/few-ways-jump.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Adds support for numeric route parameters in getStaticPaths()
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index bd45f5108..ffb62a15f 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -824,7 +824,7 @@ export interface Page<T = any> {
export type PaginateFunction = (data: [], args?: PaginateOptions) => GetStaticPathsResult;
-export type Params = Record<string, string | undefined>;
+export type Params = Record<string, string | number | undefined>;
export type Props = Record<string, unknown>;
diff --git a/packages/astro/src/core/render/route-cache.ts b/packages/astro/src/core/render/route-cache.ts
index f9ef8209d..b564a6ca6 100644
--- a/packages/astro/src/core/render/route-cache.ts
+++ b/packages/astro/src/core/render/route-cache.ts
@@ -10,6 +10,7 @@ import type {
import { LogOptions, warn, debug } from '../logger/core.js';
import { generatePaginateFunction } from './paginate.js';
+import { stringifyParams } from '../routing/params.js';
import {
validateGetStaticPathsModule,
validateGetStaticPathsResult,
@@ -17,11 +18,6 @@ import {
type RSSFn = (...args: any[]) => any;
-function stringifyParams(params: Params) {
- // Always sort keys before stringifying to make sure objects match regardless of parameter ordering
- return JSON.stringify(params, Object.keys(params).sort());
-}
-
interface CallGetStaticPathsOptions {
mod: ComponentInstance;
route: RouteData;
diff --git a/packages/astro/src/core/routing/params.ts b/packages/astro/src/core/routing/params.ts
index 04b242aa4..98071e069 100644
--- a/packages/astro/src/core/routing/params.ts
+++ b/packages/astro/src/core/routing/params.ts
@@ -1,3 +1,4 @@
+import { validateGetStaticPathsParameter } from './validation.js';
import type { Params } from '../../@types/astro';
/**
@@ -20,3 +21,25 @@ export function getParams(array: string[]) {
return fn;
}
+
+/**
+ * given a route's Params object, validate parameter
+ * values and create a stringified key for the route
+ * that can be used to match request routes
+ */
+export function stringifyParams(params: Params) {
+ // validate parameter values then stringify each value
+ const validatedParams = Object.entries(params)
+ .reduce((acc, next) => {
+ validateGetStaticPathsParameter(next);
+ const [key, value] = next;
+ acc[key] = `${value}`;
+ return acc;
+ }, {} as Params);
+
+ // Always sort keys before stringifying to make sure objects match regardless of parameter ordering
+ return JSON.stringify(
+ validatedParams,
+ Object.keys(params).sort()
+ );
+} \ No newline at end of file
diff --git a/packages/astro/src/core/routing/validation.ts b/packages/astro/src/core/routing/validation.ts
index a82ba58a3..d0dafdc15 100644
--- a/packages/astro/src/core/routing/validation.ts
+++ b/packages/astro/src/core/routing/validation.ts
@@ -2,10 +2,21 @@ import type { ComponentInstance, GetStaticPathsResult } from '../../@types/astro
import type { LogOptions } from '../logger/core';
import { warn } from '../logger/core.js';
+const VALID_PARAM_TYPES = ['string', 'number', 'undefined'];
+
interface ValidationOptions {
ssr: boolean;
}
+/** Throws error for invalid parameter in getStaticPaths() response */
+export function validateGetStaticPathsParameter([key, value]: [string, any]) {
+ if (!VALID_PARAM_TYPES.includes(typeof value)) {
+ throw new Error(
+ `[getStaticPaths] invalid route parameter for "${key}". Expected a string or number, received \`${value}\` ("${typeof value}")`
+ );
+ }
+}
+
/** Throw error for deprecated/malformed APIs */
export function validateGetStaticPathsModule(mod: ComponentInstance, { ssr }: ValidationOptions) {
if ((mod as any).createCollection) {
diff --git a/packages/astro/test/astro-get-static-paths.test.js b/packages/astro/test/astro-get-static-paths.test.js
index 3de3b58c9..c2ae40940 100644
--- a/packages/astro/test/astro-get-static-paths.test.js
+++ b/packages/astro/test/astro-get-static-paths.test.js
@@ -49,3 +49,25 @@ describe('getStaticPaths - 404 behavior', () => {
expect(res.status).to.equal(404);
});
});
+
+describe('getStaticPaths - route params type validation', () => {
+ let fixture;
+ let devServer;
+
+ before(async () => {
+ fixture = await loadFixture({ root: './fixtures/astro-get-static-paths/' });
+ devServer = await fixture.startDevServer();
+ });
+
+ it('resolves 200 on mathcing static path - string params', async () => {
+ // route provided with { params: { year: "2022", slug: "post-2" }}
+ const res = await fixture.fetch('/blog/2022/post-1');
+ expect(res.status).to.equal(200);
+ });
+
+ it('resolves 200 on matching static path - numeric params', async () => {
+ // route provided with { params: { year: 2022, slug: "post-2" }}
+ const res = await fixture.fetch('/blog/2022/post-2');
+ expect(res.status).to.equal(200);
+ })
+}) \ No newline at end of file
diff --git a/packages/astro/test/fixtures/astro-get-static-paths/src/pages/blog/[year]/[slug].astro b/packages/astro/test/fixtures/astro-get-static-paths/src/pages/blog/[year]/[slug].astro
index 12e686366..95902cf07 100644
--- a/packages/astro/test/fixtures/astro-get-static-paths/src/pages/blog/[year]/[slug].astro
+++ b/packages/astro/test/fixtures/astro-get-static-paths/src/pages/blog/[year]/[slug].astro
@@ -2,6 +2,7 @@
export async function getStaticPaths() {
return [
{ params: { year: '2022', slug: 'post-1' } },
+ { params: { year: 2022, slug: 'post-2' } },
{ params: { slug: 'post-2', year: '2022' } },
]
}