Skip to content

Commit

Permalink
Fix/numeric path params (#3087)
Browse files Browse the repository at this point in the history
* adding support for numeric params in getStaticPaths()

* chore: adding changeset

* ignore undefined params in type validation
  • Loading branch information
Tony Sullivan committed Apr 15, 2022
1 parent fa573f0 commit e0f838c
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/few-ways-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Adds support for numeric route parameters in getStaticPaths()
2 changes: 1 addition & 1 deletion packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>;

Expand Down
6 changes: 1 addition & 5 deletions packages/astro/src/core/render/route-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,14 @@ import type {
import { LogOptions, warn, debug } from '../logger/core.js';

import { generatePaginateFunction } from './paginate.js';
import { stringifyParams } from '../routing/params.js';
import {
validateGetStaticPathsModule,
validateGetStaticPathsResult,
} from '../routing/validation.js';

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;
Expand Down
23 changes: 23 additions & 0 deletions packages/astro/src/core/routing/params.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { validateGetStaticPathsParameter } from './validation.js';
import type { Params } from '../../@types/astro';

/**
Expand All @@ -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()
);
}
11 changes: 11 additions & 0 deletions packages/astro/src/core/routing/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
22 changes: 22 additions & 0 deletions packages/astro/test/astro-get-static-paths.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -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' } },
]
}
Expand Down

0 comments on commit e0f838c

Please sign in to comment.