Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Path to regexp fix #11965

Closed
wants to merge 6 commits into from
Closed

Conversation

hkbertoson
Copy link

Changes

  • What does this change? Updated path-regexp-fix to latest version
  • Be short and concise. Bullet points can help!
  • Before/after screenshots can help as well.
  • Don't forget a changeset! pnpm exec changeset

Testing

Docs

Copy link

changeset-bot bot commented Sep 10, 2024

🦋 Changeset detected

Latest commit: a06cfaa

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added pkg: astro Related to the core `astro` package (scope) semver: minor Change triggers a `minor` release labels Sep 10, 2024
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is blocked because it contains a minor changeset. A reviewer will merge this at the next release if approved.

@uwej711
Copy link
Contributor

uwej711 commented Sep 10, 2024

This is not enough, the template building in getRouteGenerator needs to be changed as (.*)? is no longer supported ... the closest to use is the wildcard, but that would require an array for the segments.

@hkbertoson
Copy link
Author

Let me take a look at that and see!

@hkbertoson
Copy link
Author

This is not enough, the template building in getRouteGenerator needs to be changed as (.*)? is no longer supported ... the closest to use is the wildcard, but that would require an array for the segments.

I updated the generator function. I tested it in several different scenarios and it seems to be working everywhere.

@@ -31,7 +33,7 @@ export function getRouteGenerator(
segment
.map((part) => {
if (part.spread) {
return `:${part.content.slice(3)}(.*)?`;
return `${part.content.slice(3)}`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removes this part from being a parameter understood by path-to-regexp to just being a literal, e.g. if the route was [...slug], previously this template literal created :slug(.*) but after this change it just creates slug. That’s probably why a lot of tests are failing.

We’ll need to check how to match the (.*) behaviour in the latest version of path-to-regexp (if possible).

Copy link
Member

@delucis delucis Sep 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From taking a look at the docs, it seems like this might be the way?

Suggested change
return `${part.content.slice(3)}`;
return `*${part.content.slice(3)}`;

In a quick sandbox I spun up I ran this code:

const { compile } = require('path-to-regexp');
const toPath = compile('/*spread/:slug');
const path = toPath({ spread: ['one','two','three'], slug: 'four' });
console.log(path);

Which logged /one/two/three/four as expected. We’d still need to see if it fully matches all behaviour specified in tests though or if there are edge cases.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this as well. It errors out and says "expected "slug" to be a non-empty array"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I guess currently we allow [...spread] to match nothing (i.e. [...spread] can match /) and *spread in path-to-regexp doesn’t include support for an optional segment. They do mention {} for optional segments, could try combining that with the wildcard?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then there is still the issue with the actual parameter value for rest (...) parameters, today it's "somedir/file.ext" and with the new version it should be ["somedir", "file.ext"], i.e. the parameter value needs to be split.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, when I did a quick investigation it looked like path-to-regexp already expected an array in v6, so assumed that hadn’t changed, but I may have misunderstood.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. I made some changes and im testing it all now to see.

hkbertoson and others added 2 commits September 11, 2024 04:39
Co-authored-by: Chris Swithinbank <[email protected]>
Sanitize parameters, preserve arrays for spread params like `slug`. Update type definitions and handle string-to-array conversion.
@@ -31,7 +37,7 @@ export function getRouteGenerator(
segment
.map((part) => {
if (part.spread) {
return `:${part.content.slice(3)}(.*)?`;
return `*${part.content.slice(3)}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be

return `{*${part.content.slice(3)}}`;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or

return `*{${part.content.slice(3)}}`;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like none of those is working ...

return (params: Record<string, string[] | number | undefined>): string => {

// Convert `slug` to an array if it's a string
if (typeof params.slug === 'string') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The array conversion should only happen for parameters which RoutePart has spread set to true. And it should split the string if it contains a /.

@blakeembrey
Copy link

Couple of things to try and help if someone is attempting this:

but that would require an array for the segments.

Set encode = false, it'll accept only strings again (and assume you've encoded it correctly beforehand).

You might also find generating TokenData directly a bit simpler: https://github.com/pillarjs/path-to-regexp?tab=readme-ov-file#developers. It was added for this use-case, so people don't need to try and generate strings that might not be safe themselves. That would look more like:

const path = new TokenData([
  { type: "text", value: "/" },
 ...segments.map(segment => {
  if (part.spread) return { type: "wildcard", name: part.content }; // Wrap in `type: "group"` if you truly want it to be optional but that seems off to me, since it'd allow `//` with nothing in between?
  if (part.dynamic) return { type: "param", name: part.content };
  return { type: "text", value: part.content.normalize() }
  });
]);

@uwej711
Copy link
Contributor

uwej711 commented Sep 12, 2024

I tried the update to and in the end think that what we used path-to-regexp for can be simply implemented without, see #11981. Maybe I overlooked some cases but all the tests are green locally.

@blakeembrey
Copy link

Good call, if you’re never using the template strings you don’t need the library. That’s basically what compile is doing already.

@hkbertoson
Copy link
Author

That actually makes sense. I was planning on looking to see if we could do that. Glad to see it should be working.

@Princesseuh
Copy link
Member

Superceded by #11983, thank you for contributing nonetheless!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: astro Related to the core `astro` package (scope) semver: minor Change triggers a `minor` release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants