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

feat(middleware/devtools): Better redux devtools. One connection for all zustand stores #1435

Merged
merged 18 commits into from
Jan 1, 2023

Conversation

pavlobu
Copy link
Contributor

@pavlobu pavlobu commented Nov 17, 2022

Related Issues - None

Fixes - A new feature for better redux devtools integration. One redux devtools connection can be used for all zustand stores.

Summary

  • one redux devtools connection for all zustand stores
  • add store devtools option to name different stores in devtoolsOptions
  • backward compatibility with old api usage
  • add devOnlyDevtools export that helps to exclude devtools from prod builds without changing code
  • add demo project in documentations
  • temporary npmjs package with this PR features: https://www.npmjs.com/package/@pavlobu/zustand

Check List

  • [v] yarn run prettier for formatting code and docs

Thank you for this awesome tool - zustand. I really enjoyed to use it and I hope my update helps!

@codesandbox-ci
Copy link

codesandbox-ci bot commented Nov 17, 2022

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 0c288a8:

Sandbox Source
React Configuration
React Typescript Configuration
React Browserify Configuration
React Snowpack Configuration
React Parcel Configuration
Next.js Configuration
@pavlobu/zustand demo Configuration

@pavlobu pavlobu changed the title Devtools one store Better redux devtools. One connection for all zustand stores Nov 17, 2022
@dai-shi
Copy link
Member

dai-shi commented Nov 17, 2022

This looks like a nice improvement.
What do you guys think? @Aslemammad @devanshj


I'm not a big fan of the complexity of the implementation.

  • any possibility to make it better?
  • tests would be required anyway.
  • process.env is not always accessible and we can't depend on it. (and we decided to let developers to control disabling the middleware)

@pavlobu
Copy link
Contributor Author

pavlobu commented Nov 17, 2022

@dai-shi, thank you for your feedback.

I could not find any better solution as of now, any suggestions?
I can try to fix those eslint failures and write some tests.
Regarding process.env do I have to use something else instead? I thought it might be useful for users to disable zustand devtools for react builds this way, but I can remove that feature if it's cumbersome.

@dai-shi
Copy link
Member

dai-shi commented Nov 17, 2022

Thanks. Yeah, for the first step, please fix eslint, add tests and remove process.env detection.
I don't have any ideas for improvements yet, but will see.

@Aslemammad
Copy link
Member

@pavlobu Can we have a Codesandbox example?

@pavlobu
Copy link
Contributor Author

pavlobu commented Nov 17, 2022

@pavlobu Can we have a Codesandbox example?

I can create and add codesandbox example here if you want:
https://github.com/pmndrs/zustand/blob/main/.codesandbox/ci.json

If you want to test this feature now, you can refer to example that I've included in my fork branch of zustand:
https://github.com/pavlobu/zustand/tree/%40pavlobu-zustand-devtools-middleware/examples/dev-env-devtools-many-stores
I've also added example demo in this PR

@Aslemammad
Copy link
Member

Thank you so much, an example in codesandbox would be so much better.

@pavlobu
Copy link
Contributor Author

pavlobu commented Nov 17, 2022

Thank you so much, an example in codesandbox would be so much better.

I tried code sandbox, but unfortunately it does not connect to redux devtools extension :(
https://codesandbox.io/s/pavlobu-zustand-demo-frutec

local build works fantastic though

@devanshj
Copy link
Contributor

devanshj commented Nov 17, 2022

This looks like a nice improvement.
What do you guys think? @Aslemammad @devanshj

I've never been a user of the redux devtools or zustand (I merely rewrote the devtools middleware), so I can't tell if like or dislike this version or even the existing version :P — an user would be able to gauge better

@Aslemammad
Copy link
Member

This PR looks good to me, the only concern I have is the complexity of the DX, would it confuse users who only want to watch one store, instead all of the other stores?

@pavlobu
Copy link
Contributor Author

pavlobu commented Nov 17, 2022

This PR looks good to me, the only concern I have is the complexity of the DX, would it confuse users who only want to watch one store, instead all of the other stores?

Thanks!
Users who only want to see one store can always type a different connection name for a store, and don't assign store in devtoolsOptions. Or it will work this way even if they don't include devtoolsOptions at all.
This implementation is backward compatible with older zustand usage apis, so it will not break people's codes if they bump zustand to a newer version if it will include this feature.
We can mention this use case in docs

Copy link
Member

@Aslemammad Aslemammad left a comment

Choose a reason for hiding this comment

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

With proper testing reviewed by @dai-shi, This PR would look fully good to me.

@dai-shi
Copy link
Member

dai-shi commented Nov 17, 2022

@devanshj

I've never been a user of the redux devtools or zustand

Oh, never mind then. I thought you have some familiarity as you filed #716, at least more then me.


@pavlobu You might be interested in looking into #716 after finishing this PR. Not sure what's left to do there.

@dai-shi
Copy link
Member

dai-shi commented Nov 17, 2022

@pavlobu

I could not find any better solution as of now, any suggestions?

I'd like to propose something to make the devtools middleware more flexible. It may also make you re-think to organize the code better, less complex, and more readable.

It's to support multiple connections for groups of stores.

image

@pavlobu
Copy link
Contributor Author

pavlobu commented Nov 17, 2022

@dai-shi I got your point, I will find a way to do such improvement.
For the code, I can do some refactoring. Np

@pavlobu
Copy link
Contributor Author

pavlobu commented Nov 18, 2022

@pavlobu

I could not find any better solution as of now, any suggestions?

I'd like to propose something to make the devtools middleware more flexible. It may also make you re-think to organize the code better, less complex, and more readable.

It's to support multiple connections for groups of stores.

image

Ok, @dai-shi we have this feature now.
I'm going to write tests before doing refactoring.
Regarding unit tests, what do you think should be tested and how many tests should we have for this feature ?

@dai-shi
Copy link
Member

dai-shi commented Nov 18, 2022

The goal of tests here is, say, if I were to refactor the code (no intention to break, but can break with mistakes), I would confirm if I did anything wrong with tests. If tests pass, we will let the release go.

readme.md Show resolved Hide resolved
src/middleware/devtools.ts Outdated Show resolved Hide resolved
@pavlobu
Copy link
Contributor Author

pavlobu commented Nov 23, 2022

@dai-shi, I've added some tests, please check if this pr is ok to go.
I agree with you that the implementation is complex and adds too many edge cases that need to be handled. I did what I could for now.

Copy link
Member

@dai-shi dai-shi left a comment

Choose a reason for hiding this comment

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

I feel like we should refactor a lot and remove edge cases, before merging this PR. Otherwise, nobody will be able to maintain it.

Comment on lines 154 to 163
const connections: Map<string | undefined, ConnectResponse> = new Map()

type ConnectionStoreApis = (StoreApi<any> & { store: string })[]
const connectionStoreApis: Map<string | undefined, ConnectionStoreApis> =
new Map()
type ConnectionInitialStoreStates = (any & { store: string })[]
const connectionInitialStoreStates: Map<
string | undefined,
ConnectionInitialStoreStates
> = new Map()
Copy link
Member

Choose a reason for hiding this comment

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

Can this be just a single map?

type Name = string | undefined // `name` option
type Store = string | undefined // `store` option
type Connections = Map<Name, [ConnectResponse, Record<Store, StoreApi<unknown>>]>

Only having one store api where store=undefined is a special case.


Oh, we need to allow having multiple name=undefined instances? That seems tricky.
Then this? 🤔

type Connections = Set<[Name, ConnectResponse, Record<Store, StoreApi<unknown>>]>

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, multiple name undefined instances is a default behavior which is not introduced by this pr. And it is not fully covered by tests

@pavlobu
Copy link
Contributor Author

pavlobu commented Nov 24, 2022

I feel like we should refactor a lot and remove edge cases, before merging this PR. Otherwise, nobody will be able to maintain it.

Hi, agree.
Unfortunately I don't know when I will have time for this.

Here are things i thought about how to do it.
Before doing any major refactoring we need to have a clear goal of what should be implemented. Maybe some diagram would help.

The edge cases are:

  1. Name undefined for multiple stores devtools() calls (default case not introduced by this pr). Connections should be separated from each other
  2. Name defined - connect stores for different names, reuse same connection for same name for different stores (this case was introduced by suggestion of improvement by @dai-shi ). Connections should be separated from each other
  3. Name undefined but store is defined in devtools call, different actions should be called when using devtools controls. Connections should be separated from each other
  4. store is defined and anonymousActionType is defined in state action. This action type should be added with store name as prefix for action type

@dai-shi
Copy link
Member

dai-shi commented Nov 28, 2022

I'm struggling with how to proceed this.
If this is really useful for developers (I personally like the idea, but don't use it. Not sure how many people use it), we might consider introducing breaking changes.
If nobody has time to work on this, it might worth considering to provide it as a third party package for now and get feedback.

@cwstra
Copy link
Contributor

cwstra commented Dec 4, 2022

@pavlobu: I thought I might take a stab at the refactor, so I made my own fork and a PR to merge it into yours. Let me know what you think.

Did not add extra test cases yet, since I didn't want to invest too much before knowing if I was stepping on toes.

@pavlobu
Copy link
Contributor Author

pavlobu commented Dec 4, 2022

@cwstra
Thanks. No extra tests were added by me so you are ok to try your approach 👍

@pavlobu
Copy link
Contributor Author

pavlobu commented Dec 13, 2022

Hi @dai-shi,
We have an update.
Thanks, @cwstra for your refactoring work!

@dai-shi
Copy link
Member

dai-shi commented Dec 15, 2022

@pavlobu @cwstra
Thanks for working on this!
Let's try to merge this. I'll review for it.

I'd appreciate if you would be willing to work on adding tests and more refactors even after merging this.

Copy link
Member

@dai-shi dai-shi left a comment

Choose a reason for hiding this comment

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

There should be more ways to do things better with refactors, but for this PR, we want small changes, and it looks good.

Please see the comments below.

}
trackedConnections.set(options.name, newConnection)
return { type: 'tracked' as const, store, ...newConnection }
})()
Copy link
Member

Choose a reason for hiding this comment

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

Are you sure we need IIFE here?

Copy link
Contributor

@cwstra cwstra Dec 31, 2022

Choose a reason for hiding this comment

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

Extracted this into a helper function in another PR I made for pavolbu's fork.

Comment on lines 181 to 183
type S = ReturnType<typeof fn> & {
[store: string]: S
}
Copy link
Member

Choose a reason for hiding this comment

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

Sure about this type? Seems very weird.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree, though it's tricky to get rid of entirely. I did manage to get it working without recursively referring to S, at least. @pavlobu might be able to explain it more; I was basically just going with it when doing the initial changes.

Comment on lines 343 to 344
JSON.stringify(api.getState()) !==
JSON.stringify(stateFromDevtools)
Copy link
Member

Choose a reason for hiding this comment

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

This seem pretty unfortunate. Wonder if we have any other solution than deep equal. Should be fine for this PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agreed. If there's a better way, it's probably in the docs for the redux devtools somewhere.

@@ -1,6 +1,7 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
Copy link
Member

Choose a reason for hiding this comment

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

What would happen if we don't add this?

Copy link
Contributor

Choose a reason for hiding this comment

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

From what I can gather by commenting it out, I think it was added so that we could do dynamic imports for the devtools tests. We want to dynamically import the tools to avoid needing to clean up connections from previous tests. @pavlobu would know for sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct @cwstra , that was done for that. To use dynamic imports inside tests.
Thanks!

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for clarification!

@pavlobu Can you elaborate why we need dynamic imports in tests?

type StoreName = string
type StoreInformation = {
api: StoreApi<unknown>
initialState: unknown
Copy link
Member

Choose a reason for hiding this comment

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

I'm not confident if we need this initialState. Can it be done with "current state" i.e. api.getState()?

Copy link
Contributor

Choose a reason for hiding this comment

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

Think I managed to hammer this away in the aforementioned PR to the fork.

@dai-shi dai-shi added this to the v4.2.0 milestone Dec 17, 2022
Copy link
Member

@dai-shi dai-shi left a comment

Choose a reason for hiding this comment

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

@pavlobu @cwstra
Can you reply to my previous comments? We want to merge this after resolving those.

@cwstra
Copy link
Contributor

cwstra commented Dec 31, 2022

Sorry for the delay, hit a wall for a bit there. Addressed some concerns in this PR on pavlobu's fork, and replied to them all.

@pavlobu
Copy link
Contributor Author

pavlobu commented Dec 31, 2022

@cwstra's changes are merged in my fork PR.
Thank you all and Happy New year!

Copy link
Member

@dai-shi dai-shi left a comment

Choose a reason for hiding this comment

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

Thanks for your work!
Let's merge it and work on other improvements afterwards.

  • @pavlobu @cwstra Adding tests and then refactoring would be very nice.
  • @chrisk-7777 Adding docs for full usage and simplifying readme would be nice.

@dai-shi dai-shi changed the title Better redux devtools. One connection for all zustand stores feat(middleware/devtools): Better redux devtools. One connection for all zustand stores Jan 1, 2023
@dai-shi dai-shi merged commit 633c7dd into pmndrs:main Jan 1, 2023
@chrisk-7777
Copy link
Collaborator

* @chrisk-7777 Adding docs for full usage and simplifying readme would be nice.

Not a problem, I'll get that organized

kodiakhq bot referenced this pull request in mheob/ef-calc Jan 30, 2023
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)

This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@mheob/eslint-config](https://togithub.com/mheob/config/tree/main/packages/eslint-config) ([source](https://togithub.com/mheob/config)) | [`^4.0.0` -> `^4.1.0`](https://renovatebot.com/diffs/npm/@mheob%2feslint-config/4.0.0/4.1.0) | [![age](https://badges.renovateapi.com/packages/npm/@mheob%2feslint-config/4.1.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@mheob%2feslint-config/4.1.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@mheob%2feslint-config/4.1.0/compatibility-slim/4.0.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@mheob%2feslint-config/4.1.0/confidence-slim/4.0.0)](https://docs.renovatebot.com/merge-confidence/) |
| [@types/react](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped)) | [`^18.0.26` -> `^18.0.27`](https://renovatebot.com/diffs/npm/@types%2freact/18.0.26/18.0.27) | [![age](https://badges.renovateapi.com/packages/npm/@types%2freact/18.0.27/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@types%2freact/18.0.27/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@types%2freact/18.0.27/compatibility-slim/18.0.26)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@types%2freact/18.0.27/confidence-slim/18.0.26)](https://docs.renovatebot.com/merge-confidence/) |
| [@vitejs/plugin-react](https://togithub.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#readme) ([source](https://togithub.com/vitejs/vite-plugin-react)) | [`^3.0.0` -> `^3.0.1`](https://renovatebot.com/diffs/npm/@vitejs%2fplugin-react/3.0.0/3.0.1) | [![age](https://badges.renovateapi.com/packages/npm/@vitejs%2fplugin-react/3.0.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@vitejs%2fplugin-react/3.0.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@vitejs%2fplugin-react/3.0.1/compatibility-slim/3.0.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@vitejs%2fplugin-react/3.0.1/confidence-slim/3.0.0)](https://docs.renovatebot.com/merge-confidence/) |
| [eslint](https://eslint.org) ([source](https://togithub.com/eslint/eslint)) | [`^8.30.0` -> `^8.32.0`](https://renovatebot.com/diffs/npm/eslint/8.30.0/8.32.0) | [![age](https://badges.renovateapi.com/packages/npm/eslint/8.32.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/eslint/8.32.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/eslint/8.32.0/compatibility-slim/8.30.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/eslint/8.32.0/confidence-slim/8.30.0)](https://docs.renovatebot.com/merge-confidence/) |
| [prettier](https://prettier.io) ([source](https://togithub.com/prettier/prettier)) | [`^2.8.1` -> `^2.8.3`](https://renovatebot.com/diffs/npm/prettier/2.8.1/2.8.3) | [![age](https://badges.renovateapi.com/packages/npm/prettier/2.8.3/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/prettier/2.8.3/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/prettier/2.8.3/compatibility-slim/2.8.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/prettier/2.8.3/confidence-slim/2.8.1)](https://docs.renovatebot.com/merge-confidence/) |
| [vite](https://togithub.com/vitejs/vite/tree/main/#readme) ([source](https://togithub.com/vitejs/vite)) | [`^4.0.3` -> `^4.0.4`](https://renovatebot.com/diffs/npm/vite/4.0.3/4.0.4) | [![age](https://badges.renovateapi.com/packages/npm/vite/4.0.4/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/vite/4.0.4/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/vite/4.0.4/compatibility-slim/4.0.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/vite/4.0.4/confidence-slim/4.0.3)](https://docs.renovatebot.com/merge-confidence/) |
| [zustand](https://togithub.com/pmndrs/zustand) | [`^4.1.5` -> `^4.3.2`](https://renovatebot.com/diffs/npm/zustand/4.1.5/4.3.2) | [![age](https://badges.renovateapi.com/packages/npm/zustand/4.3.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/zustand/4.3.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/zustand/4.3.2/compatibility-slim/4.1.5)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/zustand/4.3.2/confidence-slim/4.1.5)](https://docs.renovatebot.com/merge-confidence/) |

---

### Release Notes

<details>
<summary>mheob/config</summary>

### [`v4.1.0`](https://togithub.com/mheob/config/releases/tag/%40mheob/eslint-config%404.1.0)

[Compare Source](https://togithub.com/mheob/config/compare/@mheob/eslint-config@4.0.0...@mheob/eslint-config@4.1.0)

##### Minor Changes

-   add auto-fix for unused imports and vars --> ([#&#8203;106](https://togithub.com/mheob/config/pull/106)) by [@&#8203;mheob](https://togithub.com/mheob)

##### Patch Changes

-   bump `eslint-config-next` to `13.1.0` --> ([#&#8203;106](https://togithub.com/mheob/config/pull/106)) by [@&#8203;mheob](https://togithub.com/mheob)

</details>

<details>
<summary>vitejs/vite-plugin-react</summary>

### [`v3.0.1`](https://togithub.com/vitejs/vite-plugin-react/blob/HEAD/packages/plugin-react/CHANGELOG.md#small301-2023-01-05-small)

[Compare Source](https://togithub.com/vitejs/vite-plugin-react/compare/0aaf2e56de64d566af9636877200029ec6437918...d758a2a44b0a2cb3c206fa61166cda9d5cf58221)

-   fix: don't invalidate when code is invalid ([#&#8203;67](https://togithub.com/vitejs/vite-plugin-react/issues/67)) ([9231a86](https://togithub.com/vitejs/vite-plugin-react/commit/9231a86)), closes [#&#8203;67](https://togithub.com/vitejs/vite-plugin-react/issues/67)
-   fix(deps): update all non-major dependencies ([#&#8203;69](https://togithub.com/vitejs/vite-plugin-react/issues/69)) ([0a8e099](https://togithub.com/vitejs/vite-plugin-react/commit/0a8e099)), closes [#&#8203;69](https://togithub.com/vitejs/vite-plugin-react/issues/69)

</details>

<details>
<summary>eslint/eslint</summary>

### [`v8.32.0`](https://togithub.com/eslint/eslint/releases/tag/v8.32.0)

[Compare Source](https://togithub.com/eslint/eslint/compare/v8.31.0...v8.32.0)

#### Features

-   [`fc20f24`](https://togithub.com/eslint/eslint/commit/fc20f242a2ac073b5af6d5fca67e07a175f36c3b) feat: add suggestions for redundant wrapping in prefer-regex-literals ([#&#8203;16658](https://togithub.com/eslint/eslint/issues/16658)) (YeonJuan)

#### Bug Fixes

-   [`b4f8329`](https://togithub.com/eslint/eslint/commit/b4f8329164d7b293a1557e05b987d2a685fe1d30) fix: ignore directives for no-fallthrough ([#&#8203;16757](https://togithub.com/eslint/eslint/issues/16757)) (gfyoung)

#### Documentation

-   [`17b65ad`](https://togithub.com/eslint/eslint/commit/17b65ad10d653bb05077f21d8b1f79bee96e38d8) docs: IA Update page URL move ([#&#8203;16665](https://togithub.com/eslint/eslint/issues/16665)) (Ben Perlmutter)
-   [`5981296`](https://togithub.com/eslint/eslint/commit/5981296d5c7c86228ad766009901191fdd87d5a4) docs: fix theme switcher button ([#&#8203;16752](https://togithub.com/eslint/eslint/issues/16752)) (Sam Chen)
-   [`6669413`](https://togithub.com/eslint/eslint/commit/66694136b67277c050bd27f60050779687a88c9f) docs: deploy prerelease docs under the `/docs/next/` path ([#&#8203;16541](https://togithub.com/eslint/eslint/issues/16541)) (Nitin Kumar)
-   [`78ecfe0`](https://togithub.com/eslint/eslint/commit/78ecfe0e52c0e5780fefc8dc9a98864e48de6637) docs: use inline code for rule options name ([#&#8203;16768](https://togithub.com/eslint/eslint/issues/16768)) (Percy Ma)
-   [`fc2ea59`](https://togithub.com/eslint/eslint/commit/fc2ea598aee97beb6d768866da1ee4f63775f0c9) docs: Update README (GitHub Actions Bot)
-   [`762a872`](https://togithub.com/eslint/eslint/commit/762a8727fb3b5619cff900826053b643ca5f1162) docs: Update README (GitHub Actions Bot)

#### Chores

-   [`2952d6e`](https://togithub.com/eslint/eslint/commit/2952d6ed95811ce0971b6855d66fb7a9767a7b72) chore: sync templates/\*.md files with issue templates ([#&#8203;16758](https://togithub.com/eslint/eslint/issues/16758)) (gfyoung)
-   [`3e34418`](https://togithub.com/eslint/eslint/commit/3e34418b31664decfb2337de798feafbf985b66c) chore: Add new issues to triage project ([#&#8203;16740](https://togithub.com/eslint/eslint/issues/16740)) (Nicholas C. Zakas)

### [`v8.31.0`](https://togithub.com/eslint/eslint/releases/tag/v8.31.0)

[Compare Source](https://togithub.com/eslint/eslint/compare/v8.30.0...v8.31.0)

#### Features

-   [`52c7c73`](https://togithub.com/eslint/eslint/commit/52c7c73c052e1ec2528c6b4af78181bc30cf8cdd) feat: check assignment patterns in no-underscore-dangle ([#&#8203;16693](https://togithub.com/eslint/eslint/issues/16693)) (Milos Djermanovic)
-   [`b401cde`](https://togithub.com/eslint/eslint/commit/b401cde47d44746ff91b8feced3fb3a4e32c0e12) feat: add options to check destructuring in no-underscore-dangle ([#&#8203;16006](https://togithub.com/eslint/eslint/issues/16006)) (Morten Kaltoft)
-   [`30d0daf`](https://togithub.com/eslint/eslint/commit/30d0daf55e85a412995f6d69f47cab3fb591f2c3) feat: group properties with values in parentheses in `key-spacing` ([#&#8203;16677](https://togithub.com/eslint/eslint/issues/16677)) (Francesco Trotta)

#### Bug Fixes

-   [`35439f1`](https://togithub.com/eslint/eslint/commit/35439f1572e1a8888f7feb6c5e51a15b5582495d) fix: correct syntax error in `prefer-arrow-callback` autofix ([#&#8203;16722](https://togithub.com/eslint/eslint/issues/16722)) (Francesco Trotta)
-   [`87b2470`](https://togithub.com/eslint/eslint/commit/87b247058ed520061fe1a146b7f0e7072a94990d) fix: new instance of FlatESLint should load latest config file version ([#&#8203;16608](https://togithub.com/eslint/eslint/issues/16608)) (Milos Djermanovic)

#### Documentation

-   [`4339dc4`](https://togithub.com/eslint/eslint/commit/4339dc462d78888fe2e10acdfacd6f57245ce6ae) docs: Update README (GitHub Actions Bot)
-   [`4e4049c`](https://togithub.com/eslint/eslint/commit/4e4049c5fa355b2091afc8948690fcd7b1c1e6df) docs: optimize code block structure ([#&#8203;16669](https://togithub.com/eslint/eslint/issues/16669)) (Sam Chen)
-   [`54a7ade`](https://togithub.com/eslint/eslint/commit/54a7ade5d8e6f59554afeb9202ba6143f8afdf57) docs: do not escape code blocks of formatters examples ([#&#8203;16719](https://togithub.com/eslint/eslint/issues/16719)) (Sam Chen)
-   [`e5ecfef`](https://togithub.com/eslint/eslint/commit/e5ecfefa1c952195a3a8371f5953cc655d844079) docs: Add function call example for no-undefined ([#&#8203;16712](https://togithub.com/eslint/eslint/issues/16712)) (Elliot Huffman)
-   [`a3262f0`](https://togithub.com/eslint/eslint/commit/a3262f0a6305d2a721fac137a60c62c019b26aa4) docs: Add mastodon link ([#&#8203;16638](https://togithub.com/eslint/eslint/issues/16638)) (Amaresh  S M)
-   [`a14ccf9`](https://togithub.com/eslint/eslint/commit/a14ccf91af1122e419710f58ef494980fc4894b3) docs: clarify files property ([#&#8203;16709](https://togithub.com/eslint/eslint/issues/16709)) (Sam Chen)
-   [`3b29eb1`](https://togithub.com/eslint/eslint/commit/3b29eb14e00182614c986d8498b483a9917976e7) docs: fix npm link ([#&#8203;16710](https://togithub.com/eslint/eslint/issues/16710)) (Abdullah Osama)
-   [`a638673`](https://togithub.com/eslint/eslint/commit/a638673ee6e94344c46d12dfc988adeb3783f817) docs: fix search bar focus on `Esc` ([#&#8203;16700](https://togithub.com/eslint/eslint/issues/16700)) (Shanmughapriyan S)
-   [`f62b722`](https://togithub.com/eslint/eslint/commit/f62b722251858a5dfb157591910edbaaeb4a966f) docs: country flag missing in windows ([#&#8203;16698](https://togithub.com/eslint/eslint/issues/16698)) (Shanmughapriyan S)
-   [`4d27ec6`](https://togithub.com/eslint/eslint/commit/4d27ec6019847afabeebf592dddc014e9220057c) docs: display zh-hans in the docs language switcher ([#&#8203;16686](https://togithub.com/eslint/eslint/issues/16686)) (Percy Ma)
-   [`8bda20e`](https://togithub.com/eslint/eslint/commit/8bda20e8276c6ba17d31842fcdd63ba65476fbbd) docs: remove manually maintained anchors ([#&#8203;16685](https://togithub.com/eslint/eslint/issues/16685)) (Percy Ma)
-   [`b68440f`](https://togithub.com/eslint/eslint/commit/b68440ff2b8322fc00373792701169205c94ed94) docs: User Guide Getting Started expansion ([#&#8203;16596](https://togithub.com/eslint/eslint/issues/16596)) (Ben Perlmutter)

#### Chores

-   [`65d4e24`](https://togithub.com/eslint/eslint/commit/65d4e24c36367cd63f0eba7371820e0e81dae7aa) chore: Upgrade [@&#8203;eslint/eslintrc](https://togithub.com/eslint/eslintrc)[@&#8203;1](https://togithub.com/1).4.1 ([#&#8203;16729](https://togithub.com/eslint/eslint/issues/16729)) (Brandon Mills)
-   [`8d93081`](https://togithub.com/eslint/eslint/commit/8d93081a717f6e8b8cb60c3075cc1d7e4e655e6b) chore: fix CI failure ([#&#8203;16721](https://togithub.com/eslint/eslint/issues/16721)) (Sam Chen)
-   [`8f17247`](https://togithub.com/eslint/eslint/commit/8f17247a93240ff8a08980d8e06352e4ff4e8fe3) chore: Set up automatic updating of README ([#&#8203;16717](https://togithub.com/eslint/eslint/issues/16717)) (Nicholas C. Zakas)
-   [`4cd87cb`](https://togithub.com/eslint/eslint/commit/4cd87cb3c52412277577ba00c4fbb1aec36acc8c) ci: bump actions/stale from 6 to 7 ([#&#8203;16713](https://togithub.com/eslint/eslint/issues/16713)) (dependabot\[bot])
-   [`fd20c75`](https://togithub.com/eslint/eslint/commit/fd20c75b1059c54d598c0abaf63e7d7a80f04f32) chore: sort package.json scripts in alphabetical order ([#&#8203;16705](https://togithub.com/eslint/eslint/issues/16705)) (Darius Dzien)
-   [`10a5c78`](https://togithub.com/eslint/eslint/commit/10a5c7839370219c79f44d4206cbd7c28a72bad5) chore: update ignore patterns in `eslint.config.js` ([#&#8203;16678](https://togithub.com/eslint/eslint/issues/16678)) (Milos Djermanovic)

</details>

<details>
<summary>prettier/prettier</summary>

### [`v2.8.3`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#&#8203;283)

[Compare Source](https://togithub.com/prettier/prettier/compare/2.8.2...2.8.3)

[diff](https://togithub.com/prettier/prettier/compare/2.8.2...2.8.3)

##### Allow self-closing tags on custom elements ([#&#8203;14170](https://togithub.com/prettier/prettier/pull/14170) by [@&#8203;fisker](https://togithub.com/fisker))

See [Angular v15.1.0 release note](https://togithub.com/angular/angular/releases/tag/15.1.0) for details.



```html
// Input
<app-test/>

// Prettier 2.8.2
SyntaxError: Only void and foreign elements can be self closed "app-test" (1:1)
> 1 | <app-test/>
    | ^^^^^^^^^
  2 |

// Prettier 2.8.3
<app-test />
```

### [`v2.8.2`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#&#8203;282)

[Compare Source](https://togithub.com/prettier/prettier/compare/2.8.1...2.8.2)

[diff](https://togithub.com/prettier/prettier/compare/2.8.1...2.8.2)

##### Don't lowercase link references ([#&#8203;13155](https://togithub.com/prettier/prettier/pull/13155) by [@&#8203;DerekNonGeneric](https://togithub.com/DerekNonGeneric) & [@&#8203;fisker](https://togithub.com/fisker))



```markdown
<!-- Input -->
We now don't strictly follow the release notes format suggested by [Keep a Changelog].

[Keep a Changelog]: https://example.com/

<!-- Prettier 2.8.1 -->
We now don't strictly follow the release notes format suggested by [Keep a Changelog].

[keep a changelog]: https://example.com/
<!--
^^^^^^^^^^^^^^^^^^ lowercased
-->

<!-- Prettier 2.8.2 -->
<Same as input>
```

##### Preserve self-closing tags ([#&#8203;13691](https://togithub.com/prettier/prettier/pull/13691) by [@&#8203;dcyriller](https://togithub.com/dcyriller))



```hbs
{{! Input }}
<div />
<div></div>
<custom-component />
<custom-component></custom-component>
<i />
<i></i>
<Component />
<Component></Component>

{{! Prettier 2.8.1 }}
<div></div>
<div></div>
<custom-component></custom-component>
<custom-component></custom-component>
<i></i>
<i></i>
<Component />
<Component />

{{! Prettier 2.8.2 }}
<div />
<div></div>
<custom-component />
<custom-component></custom-component>
<i />
<i></i>
<Component />
<Component />
```

##### Allow custom "else if"-like blocks with block params ([#&#8203;13930](https://togithub.com/prettier/prettier/pull/13930) by [@&#8203;jamescdavis](https://togithub.com/jamescdavis))

[#&#8203;13507](https://togithub.com/prettier/prettier/issues/13507) added support for custom block keywords used with `else`, but failed to allow block params. This updates printer-glimmer to allow block params with custom "else if"-like blocks.



```hbs
{{! Input }}
{{#when isAtWork as |work|}}
  Ship that
  {{work}}!
{{else when isReading as |book|}}
  You can finish
  {{book}}
  eventually...
{{else}}
  Go to bed!
{{/when}}

{{! Prettier 2.8.1 }}
{{#when isAtWork as |work|}}
  Ship that
  {{work}}!
{{else when isReading}}
  You can finish
  {{book}}
  eventually...
{{else}}
  Go to bed!
{{/when}}

{{! Prettier 2.8.2 }}
{{#when isAtWork as |work|}}
  Ship that
  {{work}}!
{{else when isReading as |book|}}
  You can finish
  {{book}}
  eventually...
{{else}}
  Go to bed!
{{/when}}
```

##### Preserve empty lines between nested SCSS maps ([#&#8203;13931](https://togithub.com/prettier/prettier/pull/13931) by [@&#8203;jneander](https://togithub.com/jneander))



```scss
/* Input */
$map: (
  'one': (
     'key': 'value',
  ),

  'two': (
     'key': 'value',
  ),
)

/* Prettier 2.8.1 */
$map: (
  'one': (
     'key': 'value',
  ),
  'two': (
     'key': 'value',
  ),
)

/* Prettier 2.8.2 */
$map: (
  'one': (
     'key': 'value',
  ),

  'two': (
     'key': 'value',
  ),
)
```

##### Fix missing parentheses when an expression statement starts with `let[` ([#&#8203;14000](https://togithub.com/prettier/prettier/pull/14000), [#&#8203;14044](https://togithub.com/prettier/prettier/pull/14044) by [@&#8203;fisker](https://togithub.com/fisker), [@&#8203;thorn0](https://togithub.com/thorn0))



```jsx
// Input
(let[0] = 2);

// Prettier 2.8.1
let[0] = 2;

// Prettier 2.8.1 (second format)
SyntaxError: Unexpected token (1:5)
> 1 | let[0] = 2;
    |     ^
  2 |

// Prettier 2.8.2
(let)[0] = 2;
```

##### Fix semicolon duplicated at the end of LESS file ([#&#8203;14007](https://togithub.com/prettier/prettier/pull/14007) by [@&#8203;mvorisek](https://togithub.com/mvorisek))



```less
// Input
@&#8203;variable: {
  field: something;
};

// Prettier 2.8.1
@&#8203;variable: {
  field: something;
}; ;

// Prettier 2.8.2
@&#8203;variable: {
  field: something;
};
```

##### Fix no space after unary minus when followed by opening parenthesis in LESS ([#&#8203;14008](https://togithub.com/prettier/prettier/pull/14008) by [@&#8203;mvorisek](https://togithub.com/mvorisek))



```less
// Input
.unary_minus_single {
  margin: -(@&#8203;a);
}

.unary_minus_multi {
  margin: 0 -(@&#8203;a);
}

.binary_minus {
  margin: 0 - (@&#8203;a);
}

// Prettier 2.8.1
.unary_minus_single {
  margin: - (@&#8203;a);
}

.unary_minus_multi {
  margin: 0 - (@&#8203;a);
}

.binary_minus {
  margin: 0 - (@&#8203;a);
}

// Prettier 2.8.2
.unary_minus_single {
  margin: -(@&#8203;a);
}

.unary_minus_multi {
  margin: 0 -(@&#8203;a);
}

.binary_minus {
  margin: 0 - (@&#8203;a);
}
```

##### Do not change case of property name if inside a variable declaration in LESS ([#&#8203;14034](https://togithub.com/prettier/prettier/pull/14034) by [@&#8203;mvorisek](https://togithub.com/mvorisek))



```less
// Input
@&#8203;var: {
  preserveCase: 0;
};

// Prettier 2.8.1
@&#8203;var: {
  preservecase: 0;
};

// Prettier 2.8.2
@&#8203;var: {
  preserveCase: 0;
};
```

##### Fix formatting for auto-accessors with comments ([#&#8203;14038](https://togithub.com/prettier/prettier/pull/14038) by [@&#8203;fisker](https://togithub.com/fisker))



```jsx
// Input
class A {
  @&#8203;dec()
  // comment
  accessor b;
}

// Prettier 2.8.1
class A {
  @&#8203;dec()
  accessor // comment
  b;
}

// Prettier 2.8.1 (second format)
class A {
  @&#8203;dec()
  accessor; // comment
  b;
}

// Prettier 2.8.2
class A {
  @&#8203;dec()
  // comment
  accessor b;
}
```

##### Add parentheses for TSTypeQuery to improve readability ([#&#8203;14042](https://togithub.com/prettier/prettier/pull/14042) by [@&#8203;onishi-kohei](https://togithub.com/onishi-kohei))



```tsx
// Input
a as (typeof node.children)[number]
a as (typeof node.children)[]
a as ((typeof node.children)[number])[]

// Prettier 2.8.1
a as typeof node.children[number];
a as typeof node.children[];
a as typeof node.children[number][];

// Prettier 2.8.2
a as (typeof node.children)[number];
a as (typeof node.children)[];
a as (typeof node.children)[number][];
```

##### Fix displacing of comments in default switch case ([#&#8203;14047](https://togithub.com/prettier/prettier/pull/14047) by [@&#8203;thorn0](https://togithub.com/thorn0))

It was a regression in Prettier 2.6.0.



```jsx
// Input
switch (state) {
  default:
    result = state; // no change
    break;
}

// Prettier 2.8.1
switch (state) {
  default: // no change
    result = state;
    break;
}

// Prettier 2.8.2
switch (state) {
  default:
    result = state; // no change
    break;
}
```

##### Support type annotations on auto accessors via `babel-ts` ([#&#8203;14049](https://togithub.com/prettier/prettier/pull/14049) by [@&#8203;sosukesuzuki](https://togithub.com/sosukesuzuki))

[The bug that `@babel/parser` cannot parse auto accessors with type annotations](https://togithub.com/babel/babel/issues/15205) has been fixed. So we now support it via `babel-ts` parser.



```tsx
class Foo {
  accessor prop: number;
}
```

##### Fix formatting of empty type parameters ([#&#8203;14073](https://togithub.com/prettier/prettier/pull/14073) by [@&#8203;fisker](https://togithub.com/fisker))



```jsx
// Input
const foo: bar</* comment */> = () => baz;

// Prettier 2.8.1
Error: Comment "comment" was not printed. Please report this error!

// Prettier 2.8.2
const foo: bar</* comment */> = () => baz;
```

##### Add parentheses to head of `ExpressionStatement` instead of the whole statement ([#&#8203;14077](https://togithub.com/prettier/prettier/pull/14077) by [@&#8203;fisker](https://togithub.com/fisker))



```jsx
// Input
({}).toString.call(foo) === "[object Array]"
  ? foo.forEach(iterateArray)
  : iterateObject(foo);

// Prettier 2.8.1
({}.toString.call(foo) === "[object Array]"
  ? foo.forEach(iterateArray)
  : iterateObject(foo));

// Prettier 2.8.2
({}).toString.call(foo.forEach) === "[object Array]"
  ? foo.forEach(iterateArray)
  : iterateObject(foo);
```

##### Fix comments after directive ([#&#8203;14081](https://togithub.com/prettier/prettier/pull/14081) by [@&#8203;fisker](https://togithub.com/fisker))



```jsx
// Input
"use strict" /* comment */;

// Prettier 2.8.1 (with other js parsers except `babel`)
Error: Comment "comment" was not printed. Please report this error!

// Prettier 2.8.2
<Same as input>
```

##### Fix formatting for comments inside JSX attribute ([#&#8203;14082](https://togithub.com/prettier/prettier/pull/14082) with by [@&#8203;fisker](https://togithub.com/fisker))



```jsx
// Input
function MyFunctionComponent() {
  <button label=/*old*/"new">button</button>
}

// Prettier 2.8.1
Error: Comment "old" was not printed. Please report this error!

// Prettier 2.8.2
function MyFunctionComponent() {
  <button label=/*old*/ "new">button</button>;
}
```

##### Quote numeric keys for json-stringify parser ([#&#8203;14083](https://togithub.com/prettier/prettier/pull/14083) by [@&#8203;fisker](https://togithub.com/fisker))



```jsx
// Input
{0: 'value'}

// Prettier 2.8.1
{
  0: "value"
}

// Prettier 2.8.2
{
  "0": "value"
}
```

##### Fix removing commas from function arguments in maps ([#&#8203;14089](https://togithub.com/prettier/prettier/pull/14089) by [@&#8203;sosukesuzuki](https://togithub.com/sosukesuzuki))



```scss
/* Input */
$foo: map-fn(
  (
    "#{prop}": inner-fn($first, $second),
  )
);

/* Prettier 2.8.1 */
$foo: map-fn(("#{prop}": inner-fn($first $second)));

/* Prettier 2.8.2 */
$foo: map-fn(
  (
    "#{prop}": inner-fn($first, $second),
  )
);

```

##### Do not insert space in LESS property access ([#&#8203;14103](https://togithub.com/prettier/prettier/pull/14103) by [@&#8203;fisker](https://togithub.com/fisker))



```less
// Input
a {
  color: @&#8203;colors[@&#8203;white];
}

// Prettier 2.8.1
a {
  color: @&#8203;colors[ @&#8203;white];
}

// Prettier 2.8.2
<Same as input>
```

</details>

<details>
<summary>vitejs/vite</summary>

### [`v4.0.4`](https://togithub.com/vitejs/vite/blob/HEAD/packages/vite/CHANGELOG.md#small404-2023-01-03-small)

[Compare Source](https://togithub.com/vitejs/vite/compare/v4.0.3...v4.0.4)

-   fix: importmap should insert before module preload link ([#&#8203;11492](https://togithub.com/vitejs/vite/issues/11492)) ([25c64d7](https://togithub.com/vitejs/vite/commit/25c64d7)), closes [#&#8203;11492](https://togithub.com/vitejs/vite/issues/11492)
-   fix: server.host with ipv6 missed \[] (fix [#&#8203;11466](https://togithub.com/vitejs/vite/issues/11466)) ([#&#8203;11509](https://togithub.com/vitejs/vite/issues/11509)) ([2c38bae](https://togithub.com/vitejs/vite/commit/2c38bae)), closes [#&#8203;11466](https://togithub.com/vitejs/vite/issues/11466) [#&#8203;11509](https://togithub.com/vitejs/vite/issues/11509)
-   fix: stop considering parent URLs as public file ([#&#8203;11145](https://togithub.com/vitejs/vite/issues/11145)) ([568a014](https://togithub.com/vitejs/vite/commit/568a014)), closes [#&#8203;11145](https://togithub.com/vitejs/vite/issues/11145)
-   fix(build): invalidate chunk hash when css changed ([#&#8203;11475](https://togithub.com/vitejs/vite/issues/11475)) ([7a97a04](https://togithub.com/vitejs/vite/commit/7a97a04)), closes [#&#8203;11475](https://togithub.com/vitejs/vite/issues/11475)
-   fix(cli): ctrl+C no longer kills processes ([#&#8203;11434](https://togithub.com/vitejs/vite/issues/11434)) ([#&#8203;11518](https://togithub.com/vitejs/vite/issues/11518)) ([718fc1d](https://togithub.com/vitejs/vite/commit/718fc1d)), closes [#&#8203;11434](https://togithub.com/vitejs/vite/issues/11434) [#&#8203;11518](https://togithub.com/vitejs/vite/issues/11518)
-   fix(cli): revert ctrl+C no longer kills processes ([#&#8203;11434](https://togithub.com/vitejs/vite/issues/11434)) ([#&#8203;11518](https://togithub.com/vitejs/vite/issues/11518)) ([#&#8203;11562](https://togithub.com/vitejs/vite/issues/11562)) ([3748acb](https://togithub.com/vitejs/vite/commit/3748acb)), closes [#&#8203;11434](https://togithub.com/vitejs/vite/issues/11434) [#&#8203;11518](https://togithub.com/vitejs/vite/issues/11518) [#&#8203;11562](https://togithub.com/vitejs/vite/issues/11562)
-   fix(optimizer): check .vite/deps directory existence before removing ([#&#8203;11499](https://togithub.com/vitejs/vite/issues/11499)) ([1b043f9](https://togithub.com/vitejs/vite/commit/1b043f9)), closes [#&#8203;11499](https://togithub.com/vitejs/vite/issues/11499)
-   fix(ssr): emit js sourcemaps for ssr builds ([#&#8203;11343](https://togithub.com/vitejs/vite/issues/11343)) ([f12a1ab](https://togithub.com/vitejs/vite/commit/f12a1ab)), closes [#&#8203;11343](https://togithub.com/vitejs/vite/issues/11343)
-   chore: update license ([#&#8203;11476](https://togithub.com/vitejs/vite/issues/11476)) ([3d346c0](https://togithub.com/vitejs/vite/commit/3d346c0)), closes [#&#8203;11476](https://togithub.com/vitejs/vite/issues/11476)
-   chore(deps): update dependency [@&#8203;rollup/plugin-json](https://togithub.com/rollup/plugin-json) to v6 ([#&#8203;11553](https://togithub.com/vitejs/vite/issues/11553)) ([3647d07](https://togithub.com/vitejs/vite/commit/3647d07)), closes [#&#8203;11553](https://togithub.com/vitejs/vite/issues/11553)

</details>

<details>
<summary>pmndrs/zustand</summary>

### [`v4.3.2`](https://togithub.com/pmndrs/zustand/releases/tag/v4.3.2)

[Compare Source](https://togithub.com/pmndrs/zustand/compare/v4.3.1...v4.3.2)

There was a regression with default export (which is deprecated) in v4.3.0 and v4.3.1. This should fix it.

##### What's Changed

-   fix(vanilla,shallow): default export regression in CJS by [@&#8203;dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/zustand/pull/1531](https://togithub.com/pmndrs/zustand/pull/1531)
-   fix(middleware/persist): Fix the storage type by [@&#8203;MOZGIII](https://togithub.com/MOZGIII) in [https://github.com/pmndrs/zustand/pull/1540](https://togithub.com/pmndrs/zustand/pull/1540)

##### New Contributors

-   [@&#8203;CatMonster](https://togithub.com/CatMonster) made their first contribution in [https://github.com/pmndrs/zustand/pull/1539](https://togithub.com/pmndrs/zustand/pull/1539)
-   [@&#8203;MOZGIII](https://togithub.com/MOZGIII) made their first contribution in [https://github.com/pmndrs/zustand/pull/1540](https://togithub.com/pmndrs/zustand/pull/1540)

**Full Changelog**: pmndrs/zustand@v4.3.1...v4.3.2

### [`v4.3.1`](https://togithub.com/pmndrs/zustand/releases/tag/v4.3.1)

[Compare Source](https://togithub.com/pmndrs/zustand/compare/v4.3.0...v4.3.1)

This version supersedes v4.3.0.

#### What's Changed

-   chore: show deprecated message only in DEV by [@&#8203;dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/zustand/pull/1523](https://togithub.com/pmndrs/zustand/pull/1523)

**Full Changelog**: pmndrs/zustand@v4.3.0...v4.3.1

### [`v4.3.0`](https://togithub.com/pmndrs/zustand/releases/tag/v4.3.0)

[Compare Source](https://togithub.com/pmndrs/zustand/compare/v4.2.0...v4.3.0)

Throughout past years of development, we've learned the (mis)usage of the library. One of our goal is to provide smallest possible APIs. To go further, this version deprecates some features. They are still usable (with warnings), but will be removed in the future.

#### What's Changed

-   feat: deprecate some APIs toward v5 by [@&#8203;dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/zustand/pull/1403](https://togithub.com/pmndrs/zustand/pull/1403)
-   feat: deprecate default export by [@&#8203;dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/zustand/pull/1514](https://togithub.com/pmndrs/zustand/pull/1514)
-   fix(middleware/persist): hydrate in sync (new impl with storage option) by [@&#8203;dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/zustand/pull/1518](https://togithub.com/pmndrs/zustand/pull/1518)

#### New Contributors

-   [@&#8203;adil62](https://togithub.com/adil62) made their first contribution in [https://github.com/pmndrs/zustand/pull/1502](https://togithub.com/pmndrs/zustand/pull/1502)
-   [@&#8203;wcastand](https://togithub.com/wcastand) made their first contribution in [https://github.com/pmndrs/zustand/pull/1512](https://togithub.com/pmndrs/zustand/pull/1512)

**Full Changelog**: pmndrs/zustand@v4.2.0...v4.3.0

### [`v4.2.0`](https://togithub.com/pmndrs/zustand/releases/tag/v4.2.0)

[Compare Source](https://togithub.com/pmndrs/zustand/compare/v4.1.5...v4.2.0)

This version adds some new features in middleware.

#### What's Changed

-   feat(middleware/devtools): Better redux devtools. One connection for all zustand stores by [@&#8203;pavlobu](https://togithub.com/pavlobu) in [https://github.com/pmndrs/zustand/pull/1435](https://togithub.com/pmndrs/zustand/pull/1435)
-   feat(middleware/persist): new storage option by [@&#8203;dai-shi](https://togithub.com/dai-shi) in [https://github.com/pmndrs/zustand/pull/1463](https://togithub.com/pmndrs/zustand/pull/1463)
-   fix(build): disable esModule and re-export for nodejs by [@&#8203;barelyhuman](https://togithub.com/barelyhuman) in [https://github.com/pmndrs/zustand/pull/1486](https://togithub.com/pmndrs/zustand/pull/1486)

#### New Contributors

-   [@&#8203;Guchii](https://togithub.com/Guchii) made their first contribution in [https://github.com/pmndrs/zustand/pull/1476](https://togithub.com/pmndrs/zustand/pull/1476)
-   [@&#8203;sewera](https://togithub.com/sewera) made their first contribution in [https://github.com/pmndrs/zustand/pull/1478](https://togithub.com/pmndrs/zustand/pull/1478)
-   [@&#8203;pavlobu](https://togithub.com/pavlobu) made their first contribution in [https://github.com/pmndrs/zustand/pull/1435](https://togithub.com/pmndrs/zustand/pull/1435)

**Full Changelog**: pmndrs/zustand@v4.1.5...v4.2.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "before 4am on Monday" in timezone Europe/Berlin, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/mheob/ef-calc).
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.

6 participants