@sqlrooms/room-store 0.27.0-rc.0 → 0.27.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,6 +16,17 @@ export type BaseRoomStore<RS extends BaseRoomStoreState> = StoreApi<RS>;
16
16
  export type CreateBaseRoomSliceProps = {
17
17
  captureException?: BaseRoomStoreState['room']['captureException'];
18
18
  };
19
+ export type CreateRoomStoreOptions = {
20
+ /**
21
+ * Optional store key used for dev HMR reuse.
22
+ * Provide a project-specific key to force recreation when it changes.
23
+ */
24
+ storeKey?: string;
25
+ };
26
+ type CreateRoomStoreArgs<TFactory extends (...args: any[]) => any> = [
27
+ ...Parameters<TFactory>,
28
+ CreateRoomStoreOptions?
29
+ ];
19
30
  export declare function createBaseRoomSlice(props?: CreateBaseRoomSliceProps): StateCreator<BaseRoomStoreState>;
20
31
  /** @deprecated Use createBaseRoomSlice instead */
21
32
  export declare const createRoomSlice: typeof createBaseRoomSlice;
@@ -39,9 +50,14 @@ export declare function createRoomStore<RS extends BaseRoomStoreState>(stateCrea
39
50
  * @param stateCreatorFactory - A function that takes params and returns a Zustand state creator
40
51
  * @returns An object with createRoomStore(params) and useRoomStore(selector)
41
52
  *
53
+ * @example
54
+ * const {createRoomStore} = createRoomStoreCreator<MyRoomState>()(
55
+ * (projectId: string) => createMyRoomState(projectId),
56
+ * );
57
+ * createRoomStore('project-a', {storeKey: 'project-a'});
42
58
  */
43
59
  export declare function createRoomStoreCreator<RS extends BaseRoomStoreState>(): <TFactory extends (...args: any[]) => StateCreator<RS>>(stateCreatorFactory: TFactory) => {
44
- createRoomStore: (...args: Parameters<TFactory>) => StoreApi<RS>;
60
+ createRoomStore: (...args: CreateRoomStoreArgs<TFactory>) => StoreApi<RS>;
45
61
  useRoomStore: <T>(selector: (state: RS) => T) => T;
46
62
  };
47
63
  export declare function isRoomSliceWithInitialize(slice: unknown): slice is Required<Pick<SliceFunctions, 'initialize'>>;
@@ -1 +1 @@
1
- {"version":3,"file":"BaseRoomStore.d.ts","sourceRoot":"","sources":["../src/BaseRoomStore.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAE,QAAQ,EAAwB,MAAM,SAAS,CAAC;AAGtE,YAAY,EAAC,YAAY,EAAC,CAAC;AAE3B,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE;QACJ,WAAW,EAAE,OAAO,CAAC;QACrB,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7B,gBAAgB,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;KAC1E,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,EAAE,SAAS,kBAAkB,IAAI,QAAQ,CAAC,EAAE,CAAC,CAAC;AAExE,MAAM,MAAM,wBAAwB,GAAG;IACrC,gBAAgB,CAAC,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;CACnE,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,KAAK,CAAC,EAAE,wBAAwB,GAC/B,YAAY,CAAC,kBAAkB,CAAC,CAgClC;AACD,kDAAkD;AAClD,eAAO,MAAM,eAAe,4BAAsB,CAAC;AAEnD,wBAAgB,WAAW,CACzB,UAAU,EACV,UAAU,SAAS,UAAU,GAAG,kBAAkB,GAAG,UAAU,EAE/D,YAAY,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,KAAK,UAAU,GAC1E,YAAY,CAAC,UAAU,CAAC,CAG1B;AAED,0CAA0C;AAC1C,eAAO,MAAM,eAAe,oBAAc,CAAC;AAE3C;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,SAAS,kBAAkB,EAC3D,YAAY,EAAE,YAAY,CAAC,EAAE,CAAC;;mBAMR,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,KAAG,CAAC;EAKxD;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,SAAS,kBAAkB,MACjD,QAAQ,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,YAAY,CAAC,EAAE,CAAC,EACpE,qBAAqB,QAAQ,KAC5B;IACD,eAAe,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC,CAAC;IACjE,YAAY,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;CACpD,CAsCF;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC,CAOvD;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC,CAOpD"}
1
+ {"version":3,"file":"BaseRoomStore.d.ts","sourceRoot":"","sources":["../src/BaseRoomStore.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAE,QAAQ,EAAwB,MAAM,SAAS,CAAC;AAItE,YAAY,EAAC,YAAY,EAAC,CAAC;AAE3B,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE;QACJ,WAAW,EAAE,OAAO,CAAC;QACrB,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7B,gBAAgB,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;KAC1E,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,EAAE,SAAS,kBAAkB,IAAI,QAAQ,CAAC,EAAE,CAAC,CAAC;AAExE,MAAM,MAAM,wBAAwB,GAAG;IACrC,gBAAgB,CAAC,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,mBAAmB,CAAC,QAAQ,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,IAAI;IACnE,GAAG,UAAU,CAAC,QAAQ,CAAC;IACvB,sBAAsB,CAAC;CACxB,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,KAAK,CAAC,EAAE,wBAAwB,GAC/B,YAAY,CAAC,kBAAkB,CAAC,CAgClC;AACD,kDAAkD;AAClD,eAAO,MAAM,eAAe,4BAAsB,CAAC;AAEnD,wBAAgB,WAAW,CACzB,UAAU,EACV,UAAU,SAAS,UAAU,GAAG,kBAAkB,GAAG,UAAU,EAE/D,YAAY,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,KAAK,UAAU,GAC1E,YAAY,CAAC,UAAU,CAAC,CAG1B;AAED,0CAA0C;AAC1C,eAAO,MAAM,eAAe,oBAAc,CAAC;AAE3C;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,SAAS,kBAAkB,EAC3D,YAAY,EAAE,YAAY,CAAC,EAAE,CAAC;;mBAMR,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,KAAG,CAAC;EAKxD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,SAAS,kBAAkB,MACjD,QAAQ,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,YAAY,CAAC,EAAE,CAAC,EACpE,qBAAqB,QAAQ,KAC5B;IACD,eAAe,EAAE,CAAC,GAAG,IAAI,EAAE,mBAAmB,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC1E,YAAY,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;CACpD,CAsFF;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC,CAOvD;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC,CAOpD"}
@@ -1,5 +1,6 @@
1
1
  import { produce } from 'immer';
2
2
  import { createStore, useStore } from 'zustand';
3
+ import { DEV_HMR } from './hmr';
3
4
  export function createBaseRoomSlice(props) {
4
5
  return (_set, _get, store) => ({
5
6
  room: {
@@ -52,12 +53,53 @@ export function createRoomStore(stateCreator) {
52
53
  * @param stateCreatorFactory - A function that takes params and returns a Zustand state creator
53
54
  * @returns An object with createRoomStore(params) and useRoomStore(selector)
54
55
  *
56
+ * @example
57
+ * const {createRoomStore} = createRoomStoreCreator<MyRoomState>()(
58
+ * (projectId: string) => createMyRoomState(projectId),
59
+ * );
60
+ * createRoomStore('project-a', {storeKey: 'project-a'});
55
61
  */
56
62
  export function createRoomStoreCreator() {
57
63
  return function (stateCreatorFactory) {
64
+ const defaultStoreKey = DEV_HMR?.nextId();
58
65
  let store;
66
+ let currentStoreKey = defaultStoreKey;
67
+ function isCreateRoomStoreOptions(value) {
68
+ return typeof value === 'object' && value !== null && 'storeKey' in value;
69
+ }
59
70
  function createRoomStore(...args) {
60
- store = createStore(stateCreatorFactory(...args));
71
+ const lastArg = args[args.length - 1];
72
+ const options = isCreateRoomStoreOptions(lastArg) ? lastArg : undefined;
73
+ const factoryArgs = (options ? args.slice(0, -1) : args);
74
+ const storeKey = DEV_HMR
75
+ ? (options?.storeKey ?? defaultStoreKey)
76
+ : undefined;
77
+ // Dev-only: Check for existing store from previous hot reload
78
+ if (DEV_HMR && storeKey) {
79
+ if (currentStoreKey && currentStoreKey !== storeKey) {
80
+ const previousStore = DEV_HMR.get(currentStoreKey);
81
+ if (previousStore) {
82
+ const state = previousStore.getState();
83
+ if (isRoomSliceWithDestroy(state.room)) {
84
+ state.room.destroy().catch((error) => {
85
+ state.room.captureException(error);
86
+ });
87
+ }
88
+ }
89
+ DEV_HMR.delete(currentStoreKey);
90
+ }
91
+ currentStoreKey = storeKey;
92
+ const existingStore = DEV_HMR.get(storeKey);
93
+ if (existingStore) {
94
+ store = existingStore;
95
+ return existingStore;
96
+ }
97
+ }
98
+ store = createStore(stateCreatorFactory(...factoryArgs));
99
+ // Dev-only: Register store for HMR preservation
100
+ if (DEV_HMR && currentStoreKey) {
101
+ DEV_HMR.set(currentStoreKey, store);
102
+ }
61
103
  if (typeof window !== 'undefined') {
62
104
  (async () => {
63
105
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"BaseRoomStore.js","sourceRoot":"","sources":["../src/BaseRoomStore.ts"],"names":[],"mappings":"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","sourcesContent":["import {produce} from 'immer';\nimport {StateCreator, StoreApi, createStore, useStore} from 'zustand';\n\n// Re-export for convenience\nexport type {StateCreator};\n\nexport interface SliceFunctions {\n initialize?: () => Promise<void>;\n destroy?: () => Promise<void>;\n}\n\nexport type BaseRoomStoreState = {\n room: {\n initialized: boolean;\n initialize: () => Promise<void>;\n destroy: () => Promise<void>;\n captureException: (exception: unknown, captureContext?: unknown) => void;\n };\n};\n\nexport type BaseRoomStore<RS extends BaseRoomStoreState> = StoreApi<RS>;\n\nexport type CreateBaseRoomSliceProps = {\n captureException?: BaseRoomStoreState['room']['captureException'];\n};\n\nexport function createBaseRoomSlice(\n props?: CreateBaseRoomSliceProps,\n): StateCreator<BaseRoomStoreState> {\n return (_set, _get, store) => ({\n room: {\n initialized: false,\n initialize: async () => {\n await Promise.all(\n Object.entries(store.getState())\n .filter(\n ([key, slice]) =>\n key !== 'room' && isRoomSliceWithInitialize(slice),\n )\n .map(async ([_key, slice]) => {\n await slice.initialize();\n }),\n );\n },\n destroy: async () => {\n await Promise.all(\n Object.entries(store.getState())\n .filter(\n ([key, slice]) => key !== 'room' && isRoomSliceWithDestroy(slice),\n )\n .map(async ([_key, slice]) => {\n await slice.destroy();\n }),\n );\n },\n captureException:\n props?.captureException ??\n ((exception: unknown) => console.error(exception)),\n },\n });\n}\n/** @deprecated Use createBaseRoomSlice instead */\nexport const createRoomSlice = createBaseRoomSlice;\n\nexport function createSlice<\n SliceState,\n StoreState extends SliceState = BaseRoomStoreState & SliceState,\n>(\n sliceCreator: (...args: Parameters<StateCreator<StoreState>>) => SliceState,\n): StateCreator<SliceState> {\n return (set, get, store) =>\n sliceCreator(set, get as () => StoreState, store as StoreApi<StoreState>);\n}\n\n/** @deprecated Use createSlice instead */\nexport const createBaseSlice = createSlice;\n\n/**\n * Create a room store with custom fields and methods\n * @param initialState - The initial state and config for the room\n * @param sliceCreators - The slices to add to the room store\n * @returns The room store and a hook for accessing the room store\n */\nexport function createRoomStore<RS extends BaseRoomStoreState>(\n stateCreator: StateCreator<RS>,\n) {\n const factory = createRoomStoreCreator<BaseRoomStoreState & RS>();\n const storeCreator = factory(() => stateCreator);\n const roomStore = storeCreator.createRoomStore();\n\n function useRoomStore<T>(selector: (state: RS) => T): T {\n return storeCreator.useRoomStore(selector);\n }\n\n return {roomStore, useRoomStore};\n}\n\n/**\n * Factory to create a room store creator with custom params.\n *\n * @template RS - Room state type\n * @param stateCreatorFactory - A function that takes params and returns a Zustand state creator\n * @returns An object with createRoomStore(params) and useRoomStore(selector)\n *\n */\nexport function createRoomStoreCreator<RS extends BaseRoomStoreState>() {\n return function <TFactory extends (...args: any[]) => StateCreator<RS>>(\n stateCreatorFactory: TFactory,\n ): {\n createRoomStore: (...args: Parameters<TFactory>) => StoreApi<RS>;\n useRoomStore: <T>(selector: (state: RS) => T) => T;\n } {\n let store: StoreApi<RS> | undefined;\n\n function createRoomStore(...args: Parameters<TFactory>): StoreApi<RS> {\n store = createStore(stateCreatorFactory(...args));\n if (typeof window !== 'undefined') {\n (async () => {\n try {\n // Initialize the room\n await store.getState().room.initialize();\n // Set initialized to true after initialization\n store.setState((state) =>\n produce(state, (draft) => {\n draft.room.initialized = true;\n }),\n );\n } catch (error) {\n store.getState().room.captureException(error);\n }\n })();\n } else {\n console.warn(\n 'Skipping room store initialization. The room store should only be used on the client.',\n );\n }\n return store;\n }\n\n function useRoomStore<T>(selector: (state: RS) => T): T {\n if (!store)\n throw new Error(\n 'Room store not initialized. Call createRoomStore first.',\n );\n return useStore(store, selector);\n }\n\n return {createRoomStore, useRoomStore};\n };\n}\n\nexport function isRoomSliceWithInitialize(\n slice: unknown,\n): slice is Required<Pick<SliceFunctions, 'initialize'>> {\n return (\n typeof slice === 'object' &&\n slice !== null &&\n 'initialize' in slice &&\n typeof slice.initialize === 'function'\n );\n}\n\nexport function isRoomSliceWithDestroy(\n slice: unknown,\n): slice is Required<Pick<SliceFunctions, 'destroy'>> {\n return (\n typeof slice === 'object' &&\n slice !== null &&\n 'destroy' in slice &&\n typeof slice.destroy === 'function'\n );\n}\n"]}
1
+ {"version":3,"file":"BaseRoomStore.js","sourceRoot":"","sources":["../src/BaseRoomStore.ts"],"names":[],"mappings":"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","sourcesContent":["import {produce} from 'immer';\nimport {StateCreator, StoreApi, createStore, useStore} from 'zustand';\nimport {DEV_HMR} from './hmr';\n\n// Re-export for convenience\nexport type {StateCreator};\n\nexport interface SliceFunctions {\n initialize?: () => Promise<void>;\n destroy?: () => Promise<void>;\n}\n\nexport type BaseRoomStoreState = {\n room: {\n initialized: boolean;\n initialize: () => Promise<void>;\n destroy: () => Promise<void>;\n captureException: (exception: unknown, captureContext?: unknown) => void;\n };\n};\n\nexport type BaseRoomStore<RS extends BaseRoomStoreState> = StoreApi<RS>;\n\nexport type CreateBaseRoomSliceProps = {\n captureException?: BaseRoomStoreState['room']['captureException'];\n};\n\nexport type CreateRoomStoreOptions = {\n /**\n * Optional store key used for dev HMR reuse.\n * Provide a project-specific key to force recreation when it changes.\n */\n storeKey?: string;\n};\n\ntype CreateRoomStoreArgs<TFactory extends (...args: any[]) => any> = [\n ...Parameters<TFactory>,\n CreateRoomStoreOptions?,\n];\n\nexport function createBaseRoomSlice(\n props?: CreateBaseRoomSliceProps,\n): StateCreator<BaseRoomStoreState> {\n return (_set, _get, store) => ({\n room: {\n initialized: false,\n initialize: async () => {\n await Promise.all(\n Object.entries(store.getState())\n .filter(\n ([key, slice]) =>\n key !== 'room' && isRoomSliceWithInitialize(slice),\n )\n .map(async ([_key, slice]) => {\n await slice.initialize();\n }),\n );\n },\n destroy: async () => {\n await Promise.all(\n Object.entries(store.getState())\n .filter(\n ([key, slice]) => key !== 'room' && isRoomSliceWithDestroy(slice),\n )\n .map(async ([_key, slice]) => {\n await slice.destroy();\n }),\n );\n },\n captureException:\n props?.captureException ??\n ((exception: unknown) => console.error(exception)),\n },\n });\n}\n/** @deprecated Use createBaseRoomSlice instead */\nexport const createRoomSlice = createBaseRoomSlice;\n\nexport function createSlice<\n SliceState,\n StoreState extends SliceState = BaseRoomStoreState & SliceState,\n>(\n sliceCreator: (...args: Parameters<StateCreator<StoreState>>) => SliceState,\n): StateCreator<SliceState> {\n return (set, get, store) =>\n sliceCreator(set, get as () => StoreState, store as StoreApi<StoreState>);\n}\n\n/** @deprecated Use createSlice instead */\nexport const createBaseSlice = createSlice;\n\n/**\n * Create a room store with custom fields and methods\n * @param initialState - The initial state and config for the room\n * @param sliceCreators - The slices to add to the room store\n * @returns The room store and a hook for accessing the room store\n */\nexport function createRoomStore<RS extends BaseRoomStoreState>(\n stateCreator: StateCreator<RS>,\n) {\n const factory = createRoomStoreCreator<BaseRoomStoreState & RS>();\n const storeCreator = factory(() => stateCreator);\n const roomStore = storeCreator.createRoomStore();\n\n function useRoomStore<T>(selector: (state: RS) => T): T {\n return storeCreator.useRoomStore(selector);\n }\n\n return {roomStore, useRoomStore};\n}\n\n/**\n * Factory to create a room store creator with custom params.\n *\n * @template RS - Room state type\n * @param stateCreatorFactory - A function that takes params and returns a Zustand state creator\n * @returns An object with createRoomStore(params) and useRoomStore(selector)\n *\n * @example\n * const {createRoomStore} = createRoomStoreCreator<MyRoomState>()(\n * (projectId: string) => createMyRoomState(projectId),\n * );\n * createRoomStore('project-a', {storeKey: 'project-a'});\n */\nexport function createRoomStoreCreator<RS extends BaseRoomStoreState>() {\n return function <TFactory extends (...args: any[]) => StateCreator<RS>>(\n stateCreatorFactory: TFactory,\n ): {\n createRoomStore: (...args: CreateRoomStoreArgs<TFactory>) => StoreApi<RS>;\n useRoomStore: <T>(selector: (state: RS) => T) => T;\n } {\n const defaultStoreKey = DEV_HMR?.nextId();\n let store: StoreApi<RS> | undefined;\n let currentStoreKey: string | undefined = defaultStoreKey;\n\n function isCreateRoomStoreOptions(\n value: unknown,\n ): value is CreateRoomStoreOptions {\n return typeof value === 'object' && value !== null && 'storeKey' in value;\n }\n\n function createRoomStore(\n ...args: CreateRoomStoreArgs<TFactory>\n ): StoreApi<RS> {\n const lastArg = args[args.length - 1];\n const options = isCreateRoomStoreOptions(lastArg) ? lastArg : undefined;\n const factoryArgs = (\n options ? args.slice(0, -1) : args\n ) as Parameters<TFactory>;\n const storeKey = DEV_HMR\n ? (options?.storeKey ?? defaultStoreKey)\n : undefined;\n\n // Dev-only: Check for existing store from previous hot reload\n if (DEV_HMR && storeKey) {\n if (currentStoreKey && currentStoreKey !== storeKey) {\n const previousStore = DEV_HMR.get(currentStoreKey);\n if (previousStore) {\n const state = previousStore.getState();\n if (isRoomSliceWithDestroy(state.room)) {\n state.room.destroy().catch((error: unknown) => {\n state.room.captureException(error);\n });\n }\n }\n DEV_HMR.delete(currentStoreKey);\n }\n currentStoreKey = storeKey;\n\n const existingStore = DEV_HMR.get(storeKey);\n if (existingStore) {\n store = existingStore;\n return existingStore;\n }\n }\n\n store = createStore(stateCreatorFactory(...factoryArgs));\n\n // Dev-only: Register store for HMR preservation\n if (DEV_HMR && currentStoreKey) {\n DEV_HMR.set(currentStoreKey, store);\n }\n\n if (typeof window !== 'undefined') {\n (async () => {\n try {\n // Initialize the room\n await store.getState().room.initialize();\n // Set initialized to true after initialization\n store.setState((state) =>\n produce(state, (draft) => {\n draft.room.initialized = true;\n }),\n );\n } catch (error) {\n store.getState().room.captureException(error);\n }\n })();\n } else {\n console.warn(\n 'Skipping room store initialization. The room store should only be used on the client.',\n );\n }\n return store;\n }\n\n function useRoomStore<T>(selector: (state: RS) => T): T {\n if (!store)\n throw new Error(\n 'Room store not initialized. Call createRoomStore first.',\n );\n return useStore(store, selector);\n }\n\n return {createRoomStore, useRoomStore};\n };\n}\n\nexport function isRoomSliceWithInitialize(\n slice: unknown,\n): slice is Required<Pick<SliceFunctions, 'initialize'>> {\n return (\n typeof slice === 'object' &&\n slice !== null &&\n 'initialize' in slice &&\n typeof slice.initialize === 'function'\n );\n}\n\nexport function isRoomSliceWithDestroy(\n slice: unknown,\n): slice is Required<Pick<SliceFunctions, 'destroy'>> {\n return (\n typeof slice === 'object' &&\n slice !== null &&\n 'destroy' in slice &&\n typeof slice.destroy === 'function'\n );\n}\n"]}
package/dist/hmr.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ import { StoreApi } from 'zustand';
2
+ /**
3
+ * Dev-only: HMR store preservation utilities.
4
+ * These are isolated and tree-shakable in production builds.
5
+ *
6
+ * Returns null in production, so all usages should be guarded with:
7
+ * `if (DEV_HMR) { ... }`
8
+ *
9
+ * The problem this solves is that during hot module replacement (HMR), the
10
+ * store module would get re-executed,but the closure's store variable would be
11
+ * undefined, causing the error when components tried to use useRoomStore.
12
+ *
13
+ * The fix adds three key changes:
14
+ *
15
+ * 1. Creates a persistent registry on the window object that survives hot
16
+ * reloads. This stores all store instances by unique IDs.
17
+ * 2. Each store creator gets a unique ID. Since the counter resets on hot
18
+ * reload but stores are created in the same order, the IDs remain
19
+ * consistent across reloads.
20
+ * 3. Before creating a new store, it checks if one already exists in the
21
+ * registry from a previous hot reload. If found, it reuses the existing
22
+ * store, preserving all state and preventing initialization errors.
23
+ *
24
+ * This ensures that:
25
+ * - Store state is preserved across hot reloads
26
+ * - No "Room store not initialized" errors during development
27
+ * - The store initialization only happens once, not on every hot reload
28
+ *
29
+ */
30
+ export declare const DEV_HMR: {
31
+ nextId: () => string;
32
+ get: (id: string) => any;
33
+ set: (id: string, store: StoreApi<any>) => any;
34
+ delete: (id: string) => any;
35
+ } | null;
36
+ //# sourceMappingURL=hmr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmr.d.ts","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,SAAS,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,OAAO;;cAiBN,MAAM;cACN,MAAM,SAAS,QAAQ,CAAC,GAAG,CAAC;iBACzB,MAAM;QAEnB,CAAC"}
package/dist/hmr.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Dev-only: HMR store preservation utilities.
3
+ * These are isolated and tree-shakable in production builds.
4
+ *
5
+ * Returns null in production, so all usages should be guarded with:
6
+ * `if (DEV_HMR) { ... }`
7
+ *
8
+ * The problem this solves is that during hot module replacement (HMR), the
9
+ * store module would get re-executed,but the closure's store variable would be
10
+ * undefined, causing the error when components tried to use useRoomStore.
11
+ *
12
+ * The fix adds three key changes:
13
+ *
14
+ * 1. Creates a persistent registry on the window object that survives hot
15
+ * reloads. This stores all store instances by unique IDs.
16
+ * 2. Each store creator gets a unique ID. Since the counter resets on hot
17
+ * reload but stores are created in the same order, the IDs remain
18
+ * consistent across reloads.
19
+ * 3. Before creating a new store, it checks if one already exists in the
20
+ * registry from a previous hot reload. If found, it reuses the existing
21
+ * store, preserving all state and preventing initialization errors.
22
+ *
23
+ * This ensures that:
24
+ * - Store state is preserved across hot reloads
25
+ * - No "Room store not initialized" errors during development
26
+ * - The store initialization only happens once, not on every hot reload
27
+ *
28
+ */
29
+ export const DEV_HMR = (() => {
30
+ if (process.env.NODE_ENV === 'production') {
31
+ return null;
32
+ }
33
+ // Only initialize in development mode
34
+ const registry = typeof window !== 'undefined'
35
+ ? (window.__SQLROOMS_STORE_REGISTRY__ ??= new Map())
36
+ : new Map();
37
+ let idCounter = 0;
38
+ return {
39
+ nextId: () => `store_${idCounter++}`,
40
+ get: (id) => registry.get(id),
41
+ set: (id, store) => registry.set(id, store),
42
+ delete: (id) => registry.delete(id),
43
+ };
44
+ })();
45
+ //# sourceMappingURL=hmr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmr.js","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE;IAC3B,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,sCAAsC;IACtC,MAAM,QAAQ,GACZ,OAAO,MAAM,KAAK,WAAW;QAC3B,CAAC,CAAC,CAAE,MAAc,CAAC,2BAA2B,KAAK,IAAI,GAAG,EAGrD,CAAC;QACN,CAAC,CAAC,IAAI,GAAG,EAAyB,CAAC;IACvC,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,OAAO;QACL,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS,SAAS,EAAE,EAAE;QACpC,GAAG,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACrC,GAAG,EAAE,CAAC,EAAU,EAAE,KAAoB,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC;QAClE,MAAM,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;KAC5C,CAAC;AACJ,CAAC,CAAC,EAAE,CAAC","sourcesContent":["import {StoreApi} from 'zustand';\n\n/**\n * Dev-only: HMR store preservation utilities.\n * These are isolated and tree-shakable in production builds.\n *\n * Returns null in production, so all usages should be guarded with:\n * `if (DEV_HMR) { ... }`\n *\n * The problem this solves is that during hot module replacement (HMR), the\n * store module would get re-executed,but the closure's store variable would be\n * undefined, causing the error when components tried to use useRoomStore.\n *\n * The fix adds three key changes:\n *\n * 1. Creates a persistent registry on the window object that survives hot\n * reloads. This stores all store instances by unique IDs.\n * 2. Each store creator gets a unique ID. Since the counter resets on hot\n * reload but stores are created in the same order, the IDs remain\n * consistent across reloads.\n * 3. Before creating a new store, it checks if one already exists in the\n * registry from a previous hot reload. If found, it reuses the existing\n * store, preserving all state and preventing initialization errors.\n *\n * This ensures that:\n * - Store state is preserved across hot reloads\n * - No \"Room store not initialized\" errors during development\n * - The store initialization only happens once, not on every hot reload\n *\n */\nexport const DEV_HMR = (() => {\n if (process.env.NODE_ENV === 'production') {\n return null;\n }\n\n // Only initialize in development mode\n const registry =\n typeof window !== 'undefined'\n ? ((window as any).__SQLROOMS_STORE_REGISTRY__ ??= new Map<\n string,\n StoreApi<any>\n >())\n : new Map<string, StoreApi<any>>();\n let idCounter = 0;\n\n return {\n nextId: () => `store_${idCounter++}`,\n get: (id: string) => registry.get(id),\n set: (id: string, store: StoreApi<any>) => registry.set(id, store),\n delete: (id: string) => registry.delete(id),\n };\n})();\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlrooms/room-store",
3
- "version": "0.27.0-rc.0",
3
+ "version": "0.27.0-rc.2",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "module": "dist/index.js",
@@ -19,7 +19,7 @@
19
19
  "access": "public"
20
20
  },
21
21
  "dependencies": {
22
- "@sqlrooms/room-config": "0.27.0-rc.0",
22
+ "@sqlrooms/room-config": "0.27.0-rc.2",
23
23
  "immer": "^11.0.1",
24
24
  "zod": "^4.1.8",
25
25
  "zustand": "^5.0.8"
@@ -34,5 +34,5 @@
34
34
  "typecheck": "tsc --noEmit",
35
35
  "typedoc": "typedoc"
36
36
  },
37
- "gitHead": "ceafff23c197b8188040f8c93baf4e7d3dd4b081"
37
+ "gitHead": "eec06537352a9e760de21d7bcc77d9aa2db2a5ec"
38
38
  }