Skip to content

feat: support parameter patterns #362

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

Kakulukian
Copy link

@Kakulukian Kakulukian commented May 10, 2025

I'm planning to move to the newer version of path-to-regexp. In our codebase heavily relies on regex for parameter validation, especially in some legacy components we still have running in production.

I stumbled across this comment that mentions parameter pattern support might be coming in future versions. Based on that, I went ahead and implemented the functionality in this PR.

Feel free to ignore this PR if it doesn't align with the project's direction. I understand you may have different plans for handling parameter patterns in future versions!

@blakeembrey
Copy link
Member

@Kakulukian I wanted to let you know ASAP that I really appreciate the PR! It is the right direction, but unfortunately it's even more involved than this because I want to add it back in a way that ensures it still generates safe regexes. That sadly means more of a regex parser.

The good news, if you're interested, is that we could start with a very simple "parser" by rejecting all meta characters except |. Then add other use-cases one by one. Would that work for you?

Assuming you're up for it, I'll also separately leave some review comments.

src/index.ts Outdated
@@ -153,7 +156,29 @@ function* lexer(str: string): Generator<LexToken, LexToken> {
throw new TypeError(`Missing parameter name at ${i}: ${DEBUG_URL}`);
}

return value;
if (chars[i] === "(" && options?.pattern) {
Copy link
Member

Choose a reason for hiding this comment

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

Take a look at the previous code here: 60f2121#diff-a2a171449d862fe29692ce031981047d7ab755ae7f84c707aef80701b3ea0c80L155

I'd use that as a starting point, e.g. move the ( into the lexer itself (not part of name) and yield a PATTERN directly. Handle the fact that PATTERN is expected in a certain position in the if (param) below by doing tryConsume("PATTERN").

@Kakulukian
Copy link
Author

@Kakulukian I wanted to let you know ASAP that I really appreciate the PR! It is the right direction, but unfortunately it's even more involved than this because I want to add it back in a way that ensures it still generates safe regexes. That sadly means more of a regex parser.

The good news, if you're interested, is that we could start with a very simple "parser" by rejecting all meta characters except |. Then add other use-cases one by one. Would that work for you?

Assuming you're up for it, I'll also separately leave some review comments.

That's ok for me, updated with your suggestions :)

Copy link
Member

@blakeembrey blakeembrey left a comment

Choose a reason for hiding this comment

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

Feel free to omit the validation in this PR, and either of us can work on it in a follow up PR.

src/index.ts Outdated
while (i < chars.length && depth > 0) {
const char = chars[i];

if (INVALID_PATTERN_CHARS.includes(char)) {
Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately it’s more complex than this since you can be escaping a meta character to make it a valid character to use, so we actually need to iterate over the string and do some light parsing.

I’d also recommend leaving the parsing out of this section, as it should be part of the logic translating it into a regex as the library does accept raw tokens.

src/index.ts Outdated
@@ -579,7 +626,14 @@ function toRegExp(tokens: Flattened[], delimiter: string, keys: Keys) {
}

if (token.type === "param") {
result += `(${negate(delimiter, isSafeSegmentParam ? "" : backtrack)}+)`;
if (token.pattern) {
result += `(${token.pattern})`;
Copy link
Member

Choose a reason for hiding this comment

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

We should do the validation of the pattern here instead. Create a new function for validation so it can be expanded over time without refactoring inside this existing code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants