diff --git a/src/src/common/generic/lib/create-url/main.ts b/src/src/common/generic/lib/create-url/main.ts index fd50cfe..af12412 100644 --- a/src/src/common/generic/lib/create-url/main.ts +++ b/src/src/common/generic/lib/create-url/main.ts @@ -1,5 +1,4 @@ import { isEmpty } from "es-toolkit/compat"; -import { mapValues } from "es-toolkit/object"; import { trimStart } from "es-toolkit/string"; import type { CreateUrlInput, CreateUrlOutput } from "./types"; @@ -14,11 +13,20 @@ export function createUrl({ }: CreateUrlInput): CreateUrlOutput { const basePart = scheme && host ? `${scheme}://${host}${port ? `:${port}` : ""}` : ""; + const pathPart = path ? `/${trimStart(path, "/")}` : ""; + const queryPart = query && !isEmpty(query) - ? `?${new URLSearchParams(mapValues(query, (value) => String(value))).toString()}` + ? `?${new URLSearchParams( + Object.entries(query).flatMap(([key, value]) => + Array.isArray(value) + ? value.map((v) => [key, String(v)]) + : [[key, String(value)]], + ), + ).toString()}` : ""; + const fragmentPart = fragment ? `#${fragment}` : ""; const url = basePart + pathPart + queryPart + fragmentPart; diff --git a/src/src/common/generic/lib/create-url/types.ts b/src/src/common/generic/lib/create-url/types.ts index bb02290..4f465e5 100644 --- a/src/src/common/generic/lib/create-url/types.ts +++ b/src/src/common/generic/lib/create-url/types.ts @@ -1,6 +1,8 @@ +type QueryValue = boolean | number | string; + type AnyUrlInput = { fragment?: null | string; - query?: null | { [key: string]: boolean | number | string }; + query?: null | { [key: string]: QueryValue | QueryValue[] }; }; type AbsoluteUrlInput = AnyUrlInput & { diff --git a/src/src/isomorphic/state/hooks/use-global-state/types.ts b/src/src/isomorphic/state/hooks/use-global-state/types.ts index 53c884a..90b04d4 100644 --- a/src/src/isomorphic/state/hooks/use-global-state/types.ts +++ b/src/src/isomorphic/state/hooks/use-global-state/types.ts @@ -1,8 +1,8 @@ -import type { State, StateSubscribe } from "../../types"; +import type { ReadonlyState, State, StateSubscribe } from "../../types"; export type StateContainer = { current: State; - snapshot: State; + snapshot: ReadonlyState; subscribe: StateSubscribe; }; diff --git a/src/src/isomorphic/state/types.ts b/src/src/isomorphic/state/types.ts index ecb98f7..0d24032 100644 --- a/src/src/isomorphic/state/types.ts +++ b/src/src/isomorphic/state/types.ts @@ -1,5 +1,7 @@ import "client-only"; +import type { ReadonlyDeep } from "type-fest"; + export type NowState = { counter: number; timer: number; @@ -10,6 +12,8 @@ export type State = { now?: NowState; }; +export type ReadonlyState = ReadonlyDeep; + export type StateSubscribeCallback = (state: State) => void; export type StateUnsubscribe = () => void; diff --git a/src/src/isomorphic/{% if identity %}identity{% endif %}/hooks/use-identity/main.ts b/src/src/isomorphic/{% if identity %}identity{% endif %}/hooks/use-identity/main.ts index ef9ad27..74caae0 100644 --- a/src/src/isomorphic/{% if identity %}identity{% endif %}/hooks/use-identity/main.ts +++ b/src/src/isomorphic/{% if identity %}identity{% endif %}/hooks/use-identity/main.ts @@ -12,5 +12,5 @@ export function useIdentity({}: UseIdentityInput = {}): UseIdentityOutput { const identity = useMemo(() => ({ user: snapshot.user }), [snapshot.user]); - return useMemo(() => ({ identity }), [identity]); + return useMemo(() => ({ identity: identity }), [identity]); }