Skip to content

Commit

Permalink
Merge pull request #3327 from EskiMojo14/more-produce
Browse files Browse the repository at this point in the history
  • Loading branch information
markerikson authored May 5, 2023
2 parents a36f092 + 9d8f344 commit df861fd
Show file tree
Hide file tree
Showing 18 changed files with 626 additions and 453 deletions.
30 changes: 21 additions & 9 deletions packages/toolkit/src/createDraftSafeSelector.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
import { current, isDraft } from 'immer'
import { createSelector } from 'reselect'
import type { ImmutableHelpers } from './tsHelpers'
import { immutableHelpers } from './immer'

export type BuildCreateDraftSafeSelectorConfiguration = Pick<
ImmutableHelpers,
'isDraft' | 'current'
>

export function buildCreateDraftSafeSelector({
isDraft,
current,
}: BuildCreateDraftSafeSelectorConfiguration): typeof createSelector {
return function createDraftSafeSelector(...args: unknown[]) {
const selector = (createSelector as any)(...args)
const wrappedSelector = (value: unknown, ...rest: unknown[]) =>
selector(isDraft(value) ? current(value) : value, ...rest)
return wrappedSelector as any
}
}

/**
* "Draft-Safe" version of `reselect`'s `createSelector`:
Expand All @@ -8,11 +26,5 @@ import { createSelector } from 'reselect'
* that might be possibly outdated if the draft has been modified since.
* @public
*/
export const createDraftSafeSelector: typeof createSelector = (
...args: unknown[]
) => {
const selector = (createSelector as any)(...args)
const wrappedSelector = (value: unknown, ...rest: unknown[]) =>
selector(isDraft(value) ? current(value) : value, ...rest)
return wrappedSelector as any
}
export const createDraftSafeSelector: typeof createSelector =
buildCreateDraftSafeSelector(immutableHelpers)
33 changes: 10 additions & 23 deletions packages/toolkit/src/createReducer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { Draft } from 'immer'
import { produce as createNextState, isDraft, isDraftable } from 'immer'
import type { AnyAction, Action, Reducer } from 'redux'
import type { ActionReducerMapBuilder } from './mapBuilders'
import { executeReducerBuilderCallback } from './mapBuilders'
import type { NoInfer } from './tsHelpers'
import { makeFreezeDraftable } from './utils'
import type { ImmutableHelpers, NoInfer } from './tsHelpers'
import { immutableHelpers } from './immer'

/**
* Defines a mapping from action types to corresponding action object shapes.
Expand Down Expand Up @@ -153,25 +152,17 @@ const reducer = createReducer(
): ReducerWithInitialState<S>
}

export interface BuildCreateReducerConfiguration {
createNextState: <Base>(
base: Base,
recipe: (draft: Draft<Base>) => void | Base | Draft<Base>
) => Base
isDraft(value: any): boolean
isDraftable(value: any): boolean
}
export type BuildCreateReducerConfiguration = Pick<
ImmutableHelpers,
'createNextState' | 'isDraft' | 'isDraftable' | 'freeze'
>

export function buildCreateReducer({
createNextState,
isDraft,
isDraftable,
freeze,
}: BuildCreateReducerConfiguration): CreateReducer {
const freezeDraftable = makeFreezeDraftable({
createNextState,
isDraft,
isDraftable,
})
return function createReducer<S extends NotFunction<any>>(
initialState: S | (() => S),
mapOrBuilderCallback: (builder: ActionReducerMapBuilder<S>) => void
Expand All @@ -190,9 +181,9 @@ export function buildCreateReducer({
// Ensure the initial state gets frozen either way (if draftable)
let getInitialState: () => S
if (isStateFunction(initialState)) {
getInitialState = () => freezeDraftable(initialState())
getInitialState = () => freeze(initialState(), true)
} else {
const frozenInitialState = freezeDraftable(initialState)
const frozenInitialState = freeze(initialState, true)
getInitialState = () => frozenInitialState
}

Expand Down Expand Up @@ -256,8 +247,4 @@ export function buildCreateReducer({
}
}

export const createReducer = buildCreateReducer({
createNextState,
isDraft,
isDraftable,
})
export const createReducer = buildCreateReducer(immutableHelpers)
13 changes: 4 additions & 9 deletions packages/toolkit/src/createSlice.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { Reducer } from 'redux'
import { produce as createNextState, isDraft, isDraftable } from 'immer'
import type {
ActionCreatorWithoutPayload,
PayloadAction,
Expand All @@ -18,7 +17,7 @@ import { buildCreateReducer } from './createReducer'
import type { ActionReducerMapBuilder } from './mapBuilders'
import { executeReducerBuilderCallback } from './mapBuilders'
import type { NoInfer } from './tsHelpers'
import { makeFreezeDraftable } from './utils'
import { immutableHelpers } from './immer'

let hasWarnedAboutObjectNotation = false

Expand Down Expand Up @@ -283,7 +282,7 @@ export function buildCreateSlice(
configuration: BuildCreateSliceConfiguration
): CreateSlice {
const createReducer = buildCreateReducer(configuration)
const freezeDraftable = makeFreezeDraftable(configuration)
const { freeze } = configuration

return function createSlice<
State,
Expand Down Expand Up @@ -311,7 +310,7 @@ export function buildCreateSlice(
const initialState =
typeof options.initialState == 'function'
? options.initialState
: freezeDraftable(options.initialState)
: freeze(options.initialState)

const reducers = options.reducers || {}

Expand Down Expand Up @@ -394,8 +393,4 @@ export function buildCreateSlice(
}
}

export const createSlice = buildCreateSlice({
createNextState,
isDraft,
isDraftable,
})
export const createSlice = buildCreateSlice(immutableHelpers)
75 changes: 46 additions & 29 deletions packages/toolkit/src/entities/create_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,56 @@ import type {
EntityAdapter,
} from './models'
import { createInitialStateFactory } from './entity_state'
import { createSelectorsFactory } from './state_selectors'
import { createSortedStateAdapter } from './sorted_state_adapter'
import { createUnsortedStateAdapter } from './unsorted_state_adapter'
import { buildCreateSelectorsFactory } from './state_selectors'
import { buildCreateSortedStateAdapter } from './sorted_state_adapter'
import { buildCreateUnsortedStateAdapter } from './unsorted_state_adapter'
import type { BuildCreateDraftSafeSelectorConfiguration } from '..'
import type { BuildStateOperatorConfiguration } from './state_adapter'
import { immutableHelpers } from '../immer'

/**
*
* @param options
*
* @public
*/
export function createEntityAdapter<T>(
options: {
export interface BuildCreateEntityAdapterConfiguration
extends BuildCreateDraftSafeSelectorConfiguration,
BuildStateOperatorConfiguration {}

export type CreateEntityAdapter = {
<T>(options?: {
selectId?: IdSelector<T>
sortComparer?: false | Comparer<T>
} = {}
): EntityAdapter<T> {
const { selectId, sortComparer }: EntityDefinition<T> = {
sortComparer: false,
selectId: (instance: any) => instance.id,
...options,
}
}): EntityAdapter<T>
}

const stateFactory = createInitialStateFactory<T>()
const selectorsFactory = createSelectorsFactory<T>()
const stateAdapter = sortComparer
? createSortedStateAdapter(selectId, sortComparer)
: createUnsortedStateAdapter(selectId)
export function buildCreateEntityAdapter(
config: BuildCreateEntityAdapterConfiguration
): CreateEntityAdapter {
const createSelectorsFactory = buildCreateSelectorsFactory(config)
const createUnsortedStateAdapter = buildCreateUnsortedStateAdapter(config)
const createSortedStateAdapter = buildCreateSortedStateAdapter(config)
return function createEntityAdapter<T>(
options: {
selectId?: IdSelector<T>
sortComparer?: false | Comparer<T>
} = {}
): EntityAdapter<T> {
const { selectId, sortComparer }: EntityDefinition<T> = {
sortComparer: false,
selectId: (instance: any) => instance.id,
...options,
}

return {
selectId,
sortComparer,
...stateFactory,
...selectorsFactory,
...stateAdapter,
const stateFactory = createInitialStateFactory<T>()
const selectorsFactory = createSelectorsFactory<T>()
const stateAdapter = sortComparer
? createSortedStateAdapter(selectId, sortComparer)
: createUnsortedStateAdapter(selectId)

return {
selectId,
sortComparer,
...stateFactory,
...selectorsFactory,
...stateAdapter,
}
}
}

export const createEntityAdapter = buildCreateEntityAdapter(immutableHelpers)
Loading

0 comments on commit df861fd

Please sign in to comment.