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

Core: Migrate from qs to picoquery #28315

Open
wants to merge 23 commits into
base: next
Choose a base branch
from
Open

Core: Migrate from qs to picoquery #28315

wants to merge 23 commits into from

Conversation

43081j
Copy link
Contributor

@43081j 43081j commented Jun 23, 2024

Moves the manager-api, preview-api and ui/manager to use picoquery instead of qs - a much smaller and faster alternative.

Note that we still have qs in our overall monorepo tree, but that can be tackled in a follow-up PR.

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests (existing tests should suffice)
  • integration tests
  • end-to-end tests

Manual testing

Existing stories and tests should continue to function correctly.

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

Copy link

nx-cloud bot commented Jun 23, 2024

☁️ Nx Cloud Report

CI is running/has finished running commands for commit 4468a15. As they complete they will appear below. Click to see the status, the terminal output, and the build insights.

📂 See all runs for this CI Pipeline Execution


✅ Successfully ran 1 target

Sent with 💌 from NxCloud.

Moves the `manager-api`, `preview-api` and `ui/amanger` to use
`picoquery` instead of `qs` - a much smaller and faster alternative.

Note that we still have `qs` in our overall monorepo tree, but that can
be tackled in a follow-up PR.
@43081j 43081j marked this pull request as ready for review June 23, 2024 10:57
@shilman shilman changed the title feat: migrate from qs Core: Migrate from qs to picoquery Jun 23, 2024
@shilman
Copy link
Member

shilman commented Jun 23, 2024

Looks like there are a few extra qs references that are causing linting to fail!

@43081j
Copy link
Contributor Author

43081j commented Jun 23, 2024

whoops my mistake! i forgot to run --task check i think

looks like you got it building though. let me know if you need any changes or help

@shilman
Copy link
Member

shilman commented Jun 23, 2024

I swapped one of them over, but didn't go the extra distance to do the other two, which are a little more involved 🙈

@43081j
Copy link
Contributor Author

43081j commented Jun 23, 2024

no worries, its probably the one i left out on purpose

happy to tackle that in its own PR as long as the rest of the packages build ok

sure means we temporarily have both in the dependency tree but its small enough we'll be ok i think, and i can probably sort it fairly soon

Uses the `foo.bar[0]` syntax picoquery provides, rather than dot-syntax
(`foo.bar.0`).
@43081j
Copy link
Contributor Author

43081j commented Jun 24, 2024

note there's still one usage left i need to tackle

i have failing tests locally for it but will get to it at some point 👍

Moves the preview api to use picoquery.

Note that tests will not pass yet.
Copy link
Member

@ghengeveld ghengeveld left a comment

Choose a reason for hiding this comment

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

I'm happy to move from qs to picoquery, but only if it involves no functional changes. Unfortunately, it seems picoquery urlencodes args, which aren't currently encoded. This would be a breaking change and make the URLs look really ugly, so I'm opposed to changing that behavior.

code/lib/preview-api/src/modules/preview-web/UrlStore.ts Outdated Show resolved Hide resolved
code/lib/preview-api/src/modules/preview-web/UrlStore.ts Outdated Show resolved Hide resolved
code/lib/preview-api/src/modules/preview-web/UrlStore.ts Outdated Show resolved Hide resolved
code/lib/router/src/utils.test.ts Outdated Show resolved Hide resolved
Comment on lines 158 to 159
export const queryFromLocation = (location: Partial<Location>) =>
queryFromString(location.search ? location.search.slice(1) : '');
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
export const queryFromLocation = (location: Partial<Location>) =>
queryFromString(location.search ? location.search.slice(1) : '');
export const queryFromLocation = (location: Partial<Location>) =>
queryFromString(location.search.slice(1));


export const stringifyQueryParams = (queryParams: Record<string, string>) =>
qs.stringify(queryParams, { addQueryPrefix: true, encode: false }).replace(/^\?/, '&');
Copy link
Member

Choose a reason for hiding this comment

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

I think we need some unit tests to verify stringifyQueryParams doesn't change between the two implementations.

@43081j
Copy link
Contributor Author

43081j commented Jun 25, 2024

I'm happy to move from qs to picoquery, but only if it involves no functional changes. Unfortunately, it seems picoquery urlencodes args, which aren't currently encoded. This would be a breaking change and make the URLs look really ugly, so I'm opposed to changing that behavior.

this is true, however it is doing the right thing here while qs/storybook hasn't been

the URI spec defines it this way, and is why URLSearchParams also encodes them

so we're blocked here i guess. i understand the URLs looked nicer, but they're non-standard and its unlikely pq will ever support that (since it is trying to conform to the standard and be interchangeable with URLSearchParams in those cases)

the dependency tree & package size reduction is what i've been chipping away at for months now. it'd be a shame to back off from that for nice looking URLs, especially given qs is the last piece before we shed a bunch of weight (the last connection to a deep subtree of deps)

alternatively, we could have code inside storybook which literally does replace('%3B', '[') etc. i'm not a fan but at least it doesn't result in veering away from standards in PQ and can live here instead

@ghengeveld
Copy link
Member

alternatively, we could have code inside storybook which literally does replace('%3B', '[') etc. i'm not a fan but at least it doesn't result in veering away from standards in PQ and can live here instead

That works for me. It's hacky but at least it's consistent. If being noncompliant turns out to be an issue then we can always change it in a major version release (in which case I'd opt for a different/custom array encoding to avoid %5B / %5D).

@43081j
Copy link
Contributor Author

43081j commented Jun 25, 2024

no worries, that works for me too

we already do some transforms on the parsed and stringified queries so it won't be much to add to that

Decodes certain chars we want to keep in our URIs (e.g. `[`).
@43081j
Copy link
Contributor Author

43081j commented Jun 25, 2024

we have some failures ill have to get to at some point another day 👍

basically what to do about invalid keys since pq will deal with them differently than qs did (for perf mostly)

e.g. a[b:val will likely result in {a: []}

@ghengeveld
Copy link
Member

ghengeveld commented Jun 25, 2024

basically what to do about invalid keys since pq will deal with them differently than qs did (for perf mostly)

e.g. a[b:val will likely result in {a: []}

That’s okay. Invalid input doesn’t need to be parsed in any particular way. The most important thing is that data must deserialize back to what it was before serialization, to the extent that that’s possible.

@43081j
Copy link
Contributor Author

43081j commented Jun 28, 2024

i have a busy few days ahead and some travel coming up but ill get to this when i can 👍

will ping you when i manage to fix the remaining tests

@43081j
Copy link
Contributor Author

43081j commented Jul 28, 2024

just picking this up again @ghengeveld , any idea what this kind of stuff was trying to catch?

      expect(parseArgsParam('obj.foo[][a!b]:val;obj.foo.bar:val;obj.baz:val')).toStrictEqual({});

this syntax isn't valid anywhere really, obj.foo[][a!b]. qs does what it can with it, but its meant to be obj[foo][][a!b] or obj.foo[].a!b, etc. these inputs are pretty inconsistent, mixing dot-syntax and bracket-syntax

ultimately, its trying to test that nested keys are checked for validity. so maybe i can just update these to be more sensible inputs?

edit: did what i could, think i managed to sort it out. those tests could probably do with a rewrite given how specific they are to qs behaviour (but in another PR)

Comment on lines +178 to +179
case '%20':
return '+';
Copy link
Contributor

Choose a reason for hiding this comment

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

Based on this test above, I think we need to decode both + and space here, but I can't figure out if that will be losy: https://github.com/storybookjs/storybook/pull/28315/files#diff-64b8b645dd34caca610919aa0a64fec210cbce8ca52bbb9a6d10b05d32f72ac4R61

Suggested change
case '%20':
return '+';
case '%20': // space
case '%2B': // +
return '+';

Copy link
Contributor

Choose a reason for hiding this comment

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

Either way, I don't think it matters right now, because when trying out a Date-control on next, a Date arg always turns into the UNIX time number , and never the special value !date(ISO...).

It's probably because of these lines, which have been here since the very beginning: https://github.com/storybookjs/storybook/blob/next/code/lib/blocks/src/controls/Date.tsx/#L93-L96

I'm assuming this is a bug still @ghengeveld?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah I suspect if we decode +, we lose the knowledge of if it was a space or a plus. but maybe that loss is ok since we treat both as a space? 🤔

I'm not really sure of the best thing to do here. you will know better than I do, so I'm happy to go with whatever you and the others decide

@JReinhold JReinhold assigned JReinhold and 43081j and unassigned shilman Sep 17, 2024
const args = parseArgsParam('key:!date(2001-02-03T04:05:06.789+09:00)');
const args = parseArgsParam('key:!date(2001-02-03T04:05:06.789%2B09:00)');
Copy link
Member

Choose a reason for hiding this comment

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

Are all these updated tests not indications that this is backwards incompatible, and we should delay merging this until the next major version @JReinhold ?

Copy link
Member

Choose a reason for hiding this comment

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

I don't agree with this updated format to begin with. + is valid in a URL. Moreover, this is fully client-side URL parsing so we don't even have to adhere to the specs necessarily.

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

Successfully merging this pull request may close these issues.

5 participants