kentcdodds / match-sorter

Simple, expected, and deterministic best-match sorting of an array in JavaScript
https://npm.im/match-sorter
MIT License
3.73k stars 129 forks source link

feat: allow array notation in keys #136

Closed dgattey closed 2 years ago

dgattey commented 2 years ago

What: Allows using array notation in keys (except for the wildcard value), making expressions like foo[0].first or foo.*[complex.key].last possible. Does so via a matchAll and a replace within the getNestedValues function. Backwards compatible with all the current tests, just adding support for the new syntax in addition to the currently-supported dot notation.

Why: Fixes #135 to allow for more complex expressions for array notation keys. Allows more compatibility with existing usage without breaking anything that already works.

How: Isolated where the keys were being split and converted to nested properties, then wrote a (failing at the time) test for new syntax. Then figured out how to split the keys array on a complex notation and iterated until it worked! Didn't fix the wildcard case, as there's no need to allow that to be in array notation.

Checklist:

cschubiner commented 2 years ago

I'd love for this to get in!

kentcdodds commented 2 years ago

Hmmm... What's the use case here? It just seems a little more complex than I would want it to be. Maybe there's a simpler approach that would satisfy the use case?

dgattey commented 2 years ago

The use case is for nested objects + keys that have periods in them (or other special characters):

{
  child: {
    basicKey: 'value',
    'complex.key': 'otherValue'
  }
}

I can't access that with any current keys syntax, as far as I understand the docs + code.

Happy to find a simpler use case! I couldn't think of another solution but I'm less familiar with the code than you of course.

kentcdodds commented 2 years ago

Maybe we could do what Remix does by wrapping anything we want escaped with [ and ]: https://github.com/remix-run/remix/blob/main/packages/remix-dev/config/routesConvention.ts: https://remix.run/docs/en/v1/api/conventions#escaping-special-characters

dgattey commented 2 years ago

@kentcdodds Huh, isn't that exactly what I'm doing here? I'm using anything surrounded with [ and ] as a single key, even if it contains . inside it. The code you linked from Remix is more complex, but looks like it accomplishes almost the same thing. The only difference would be multiple layers of [ ], right? For a path segment, you're not going to need more than one layer of nesting, as far as I can tell.

I used matchAll from ES2020 instead of something compatible with node 10 and 12 like it looks like the checks run, but otherwise this would be ready to go. I'll fix it up to use match or something else that's a little more simple if possible. Otherwise, can you validate that there's not some subtle difference with the Remix code I'm missing? Thanks!

kentcdodds commented 2 years ago

What you have here could be fine. I think I'm just a bit confused by all the *s and stuff 🤔

dgattey commented 2 years ago

okay, figured out another way to accomplish what I want to with the callback type of key. Thanks for entertaining this idea! Basically, I mapped my results to a simpler nesting structure, then just used keys with an object instead of a string to pull out what I needed. No need for this after all.