{"version":3,"file":"createSlice.mjs","sources":["../../../../src/lib/state/core/createSlice.ts"],"sourcesContent":["/**\n * @file Slice Factory\n * @description Type-safe slice creation with automatic action naming for DevTools\n */\n\nimport type { Draft } from 'immer';\nimport type { StateCreator } from 'zustand';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Slice setter with automatic action naming\n * Wraps the standard set function to add DevTools action names\n */\nexport type SliceSetter<TState> = {\n  /**\n   * Update state with an updater function (Immer-style)\n   * @param updater - Function that mutates draft state\n   * @param actionName - Optional action name for DevTools\n   */\n  (updater: (state: Draft<TState>) => void, actionName?: string): void;\n  /**\n   * Update state with partial state\n   * @param partial - Partial state to merge\n   * @param actionName - Optional action name for DevTools\n   */\n  (partial: Partial<TState>, actionName?: string): void;\n};\n\n/**\n * Slice getter that returns only slice state\n */\nexport type SliceGetter<TState> = () => TState;\n\n/**\n * Slice configuration\n */\nexport interface SliceConfig<TState, TActions> {\n  /** Slice name (used in DevTools action prefixes) */\n  name: string;\n  /** Initial state */\n  initialState: TState;\n  /** Action creators */\n  actions: (set: SliceSetter<TState>, get: SliceGetter<TState>) => TActions;\n}\n\n// ============================================================================\n// Slice Factory\n// ============================================================================\n\n/**\n * Create a type-safe slice with automatic action naming\n *\n * Features:\n * - Automatic action naming for DevTools (format: \"sliceName/actionName\")\n * - Immer-compatible state updates\n * - Slice-scoped getter that only returns slice state\n * - Full TypeScript inference\n *\n * @example\n * ```typescript\n * export const counterSlice = createSlice({\n *   name: 'counter',\n *   initialState: { count: 0 },\n *   actions: (set, get) => ({\n *     increment: () => {\n *       set((state) => { state.count += 1 }, 'increment');\n *     },\n *     decrement: () => {\n *       set((state) => { state.count -= 1 }, 'decrement');\n *     },\n *     incrementBy: (amount: number) => {\n *       set((state) => { state.count += amount }, 'incrementBy');\n *     },\n *     getCount: () => get().count,\n *   }),\n * });\n * ```\n */\nexport function createSlice<\n  TState extends object,\n  TActions extends Record<string, (...args: never[]) => unknown>,\n  TStore extends TState & TActions = TState & TActions,\n>(\n  config: SliceConfig<TState, TActions>\n): StateCreator<\n  TStore,\n  [['zustand/immer', never], ['zustand/devtools', never]],\n  [],\n  TState & TActions\n> {\n  const { name, initialState, actions } = config;\n\n  return (set, get) => {\n    // Create named setter that prefixes action names with slice name\n    const namedSet: SliceSetter<TState> = (\n      updaterOrPartial: ((state: Draft<TState>) => void) | Partial<TState>,\n      actionName?: string\n    ) => {\n      const type =\n        actionName != null && actionName !== '' ? `${name}/${actionName}` : `${name}/update`;\n\n      if (typeof updaterOrPartial === 'function') {\n        // Immer-style updater function - the updater for TState is compatible with TStore which extends TState\n        const storeUpdater = (state: Draft<TStore>): void => {\n          updaterOrPartial(state as unknown as Draft<TState>);\n        };\n        (\n          set as (\n            updater: (state: Draft<TStore>) => void,\n            replace: boolean,\n            action: { type: string }\n          ) => void\n        )(storeUpdater, false, { type });\n      } else {\n        // Partial state update\n        (set as (partial: Partial<TStore>, replace: boolean, action: { type: string }) => void)(\n          updaterOrPartial as unknown as Partial<TStore>,\n          false,\n          { type }\n        );\n      }\n    };\n\n    // Create slice-scoped getter that extracts only slice state\n    const sliceGet: SliceGetter<TState> = (): TState => {\n      const state = get();\n      const sliceState = {} as TState;\n      for (const key of Object.keys(initialState)) {\n        (sliceState as Record<string, unknown>)[key] = (state as Record<string, unknown>)[key];\n      }\n      return sliceState;\n    };\n\n    // Create actions with named setter and scoped getter\n    const sliceActions = actions(namedSet, sliceGet);\n\n    return {\n      ...initialState,\n      ...sliceActions,\n    };\n  };\n}\n\n// ============================================================================\n// Utility Types\n// ============================================================================\n\n/**\n * Extract state type from a slice config\n */\nexport type SliceState<T> = T extends SliceConfig<infer S, unknown> ? S : never;\n\n/**\n * Extract actions type from a slice config\n */\nexport type SliceActions<T> = T extends SliceConfig<unknown, infer A> ? A : never;\n\n/**\n * Extract full slice type (state + actions) from a slice config\n */\nexport type SliceType<T> = T extends SliceConfig<infer S, infer A> ? S & A : never;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Create a simple action creator (for use outside createSlice)\n *\n * @example\n * ```typescript\n * const increment = createAction<number>('counter/increment', (set) => (amount) => {\n *   set((state) => { state.count += amount });\n * });\n * ```\n */\nexport function createAction<TPayload = void, TState = unknown>(\n  _type: string,\n  handler: (\n    set: (updater: (state: Draft<TState>) => void) => void\n  ) => TPayload extends void ? () => void : (payload: TPayload) => void\n): TPayload extends void ? () => void : (payload: TPayload) => void {\n  // This is a placeholder that will be bound to actual set when used\n  return handler((_updater) => {\n    // Intentionally no-op - action not bound to store\n  }) as TPayload extends void ? () => void : (payload: TPayload) => void;\n}\n\n/**\n * Combine multiple slices into a single state creator\n *\n * @example\n * ```typescript\n * const useStore = create(\n *   combineSlices(counterSlice, uiSlice, settingsSlice)\n * );\n * ```\n */\nexport function combineSlices<T extends object>(\n  ...slices: StateCreator<T, [['zustand/immer', never], ['zustand/devtools', never]], [], T>[]\n): StateCreator<T, [['zustand/immer', never], ['zustand/devtools', never]], [], T> {\n  return (...args) => {\n    return slices.reduce(\n      (acc, slice) => ({\n        ...acc,\n        ...slice(...args),\n      }),\n      {} as T\n    );\n  };\n}\n"],"names":["createSlice","config","name","initialState","actions","set","get","sliceActions","updaterOrPartial","actionName","type","state","sliceState","key","createAction","_type","handler","_updater","combineSlices","slices","args","acc","slice"],"mappings":"AAiFO,SAASA,EAKdC,GAMA;AACA,QAAM,EAAE,MAAAC,GAAM,cAAAC,GAAc,SAAAC,EAAA,IAAYH;AAExC,SAAO,CAACI,GAAKC,MAAQ;AA0CnB,UAAMC,IAAeH,EAxCiB,CACpCI,GACAC,MACG;AACH,YAAMC,IACJD,KAAc,QAAQA,MAAe,KAAK,GAAGP,CAAI,IAAIO,CAAU,KAAK,GAAGP,CAAI;AAE7E,MAAI,OAAOM,KAAqB,aAM5BH,EAJmB,CAACM,MAA+B;AACnD,QAAAH,EAAiBG,CAAiC;AAAA,MACpD,GAOgB,IAAO,EAAE,MAAAD,GAAM,IAG9BL;AAAA,QACCG;AAAA,QACA;AAAA,QACA,EAAE,MAAAE,EAAA;AAAA,MAAK;AAAA,IAGb,GAGsC,MAAc;AAClD,YAAMC,IAAQL,EAAA,GACRM,IAAa,CAAA;AACnB,iBAAWC,KAAO,OAAO,KAAKV,CAAY;AACvC,QAAAS,EAAuCC,CAAG,IAAKF,EAAkCE,CAAG;AAEvF,aAAOD;AAAA,IACT,CAG+C;AAE/C,WAAO;AAAA,MACL,GAAGT;AAAA,MACH,GAAGI;AAAA,IAAA;AAAA,EAEP;AACF;AAmCO,SAASO,EACdC,GACAC,GAGkE;AAElE,SAAOA,EAAQ,CAACC,MAAa;AAAA,EAE7B,CAAC;AACH;AAYO,SAASC,KACXC,GAC8E;AACjF,SAAO,IAAIC,MACFD,EAAO;AAAA,IACZ,CAACE,GAAKC,OAAW;AAAA,MACf,GAAGD;AAAA,MACH,GAAGC,EAAM,GAAGF,CAAI;AAAA,IAAA;AAAA,IAElB,CAAA;AAAA,EAAC;AAGP;"}