zustandのmiddleware wrapperを作成してみました

# 概要
Qiita初投稿です。
Reactのzustandで個人的によく使うmiddlewareである
- devtools
- immer
- persist
を毎回記述するのが面倒だったのと
Chrome拡張機能であるReduxDevToolsでzustandのstoreを見てみると
Action名が anonymous になり、以下のディスカッションでset時にAction名を指定できるとなっているがそれも面倒...ということでAction名の設定と上記middlewareをラップした関数を作成してみました。
https://github.com/pmndrs/zustand/discussions/1668

# 環境
CodeSandBoxで作成してみました。
依存関係などはそちらをご覧ください。
https://codesandbox.io/p/devbox/zustand-wrapper-r8vvnv?file=%2Fsrc%2Fstore-wrapper.ts%3A76%2C26

# ソース
CodeSandBoxの「/src/store-wrapper.ts」ファイルが作成した関数です。


createStoreとcreatePersistStoreの2つの関数を定義しています。
immerを使用していて、WritableDraftで値をsetするときには関数になるので、functionであればfunctionの内容をそのままAction名にしています。

```ts
import { create, type StateCreator } from "zustand";
import { PersistOptions } from "zustand/middleware";
import { persist } from "zustand/middleware";
import { devtools } from "zustand/middleware";
import { immer } from "zustand/middleware/immer";

export const createStore = <T extends object>(
  stateCreator: StateCreator<
    T,
    [["zustand/immer", never], ["zustand/devtools", never]],
    []
  >,
  name?: string,
) => {
  if (import.meta.env.DEV) {
    return create<T, [["zustand/devtools", never], ["zustand/immer", never]]>(
      devtools<T, [], [["zustand/immer", never]]>(
        immer<T, [["zustand/devtools", never]], []>((set, ...other) =>
          stateCreator(
            (args, rep) => {
              let actName = "";
              if (typeof args === "function") {
                actName = args.toString();
              } else {
                actName = `set ${Object.keys(args).join(", ")}`;
              }
              return set(args, rep, actName);
            },
            ...other,
          ),
        ),
        {
          name: name,
        },
      ),
    );
  } else {
    return create<T, [["zustand/immer", never]]>(
      immer<T, [], []>((...prop) => stateCreator(...prop)),
    );
  }
};

export const createPersistStore = <T extends object>(
	stateCreator: StateCreator<
		T,
		[
			['zustand/devtools', never],
			['zustand/persist', unknown],
			['zustand/immer', never]
		],
		[]
	>,
	opt: PersistOptions<T, unknown>
) => {
	if (import.meta.env.DEV) {
		return create<
			T,
			[
				['zustand/devtools', never],
				['zustand/persist', unknown],
				['zustand/immer', never]
			]
		>(
			devtools<T, [], [['zustand/persist', unknown], ['zustand/immer', never]]>(
				persist<
					T,
					[['zustand/devtools', never]],
					[['zustand/immer', never]],
					unknown
				>(
					immer<
						T,
						[['zustand/devtools', never], ['zustand/persist', unknown]],
						[]
					>((set, ...other) =>
						stateCreator((args, rep) => {
							let actName = ''
							if (typeof args === 'function') {
								actName = args.toString()
							} else {
								actName = `set ${Object.keys(args).join(', ')}`
							}

							return set(args, rep, actName)
						}, ...other)
					),
					opt
				),
				{
					name: opt.name
				}
			)
		)
	} else {
		return create<T, [['zustand/persist', unknown], ['zustand/immer', never]]>(
			persist(
				immer<T, [['zustand/persist', unknown]], []>((...props) =>
					stateCreator(...props)
				),
				opt
			)
		)
	}
}
```

# まとめ
上記のようなソースコードを色々探してみたのですが、なかなか見つからなかったので自作してみました。
同じような悩みを抱えている方の参考になれば幸いです。
ここをこうしたらもっと良くなるよ！など、アドバイスがあれば教えてください。