react-optimistic-chat 3.0.0 → 3.0.1

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.
package/dist/index.d.mts CHANGED
@@ -1,7 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
3
  import * as _tanstack_query_core from '@tanstack/query-core';
4
- import { InfiniteData } from '@tanstack/react-query';
5
4
 
6
5
  type ChatRole = "AI" | "USER";
7
6
  type BaseMessage = {
@@ -103,24 +102,33 @@ type CommonProps = {
103
102
  type Props<Raw> = CommonProps & (MessageProps | RawProps<Raw>);
104
103
  declare function ChatContainer<Raw>(props: Props<Raw>): react_jsx_runtime.JSX.Element;
105
104
 
106
- type ExtractCustom$1<Raw> = Omit<Raw, keyof BaseMessage>;
107
- type Options$2<Raw> = {
105
+ type KeyMap<Raw extends Record<string, unknown>> = {
106
+ id: keyof Raw;
107
+ role: keyof Raw;
108
+ content: keyof Raw;
109
+ };
110
+ type Custom<Raw extends Record<string, unknown>, Map extends KeyMap<Raw>> = Omit<Raw, Map["id" | "role" | "content"]>;
111
+
112
+ type MessagePage<Raw extends Record<string, unknown>, Map extends KeyMap<Raw>> = Message<Custom<Raw, Map>>[];
113
+
114
+ type Options$2<Raw extends Record<string, unknown>, Map extends KeyMap<Raw> = KeyMap<Raw>> = {
108
115
  queryKey: readonly unknown[];
109
116
  queryFn: (pageParam: unknown) => Promise<Raw[]>;
110
117
  initialPageParam: unknown;
111
- getNextPageParam: (lastPage: Message<ExtractCustom$1<Raw>>[], allPages: Message<ExtractCustom$1<Raw>>[][]) => unknown;
118
+ getNextPageParam: (lastPage: MessagePage<Raw, Map>, allPages: MessagePage<Raw, Map>[]) => unknown;
112
119
  mutationFn: (content: string) => Promise<Raw>;
113
- map: (raw: Raw) => MessageCore;
120
+ keyMap: Map;
121
+ roleResolver: (value: Raw[Map["role"]]) => MessageCore["role"];
114
122
  onError?: (error: unknown) => void;
115
123
  staleTime?: number;
116
124
  gcTime?: number;
117
125
  };
118
- declare function useChat<Raw extends object>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, map, onError, staleTime, gcTime, }: Options$2<Raw>): {
119
- messages: Message<ExtractCustom$1<Raw>>[];
126
+ declare function useChat<Raw extends Record<string, unknown>, Map extends KeyMap<Raw>>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, keyMap, roleResolver, onError, staleTime, gcTime, }: Options$2<Raw, Map>): {
127
+ messages: Message<Custom<Raw, Map>>[];
120
128
  sendUserMessage: (content: string) => void;
121
129
  isPending: boolean;
122
130
  isInitialLoading: boolean;
123
- fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<InfiniteData<Message<ExtractCustom$1<Raw>>[], unknown>, Error>>;
131
+ fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<_tanstack_query_core.InfiniteData<MessagePage<Raw, Map>, unknown>, Error>>;
124
132
  hasNextPage: boolean;
125
133
  isFetchingNextPage: boolean;
126
134
  };
@@ -195,26 +203,26 @@ declare function useBrowserSpeechRecognition({ lang, onStart, onEnd, onError, }?
195
203
  onTranscript: (text: string) => void;
196
204
  };
197
205
 
198
- type ExtractCustom<Raw> = Omit<Raw, keyof BaseMessage>;
199
- type Options<Raw> = {
206
+ type Options<Raw extends Record<string, unknown>, Map extends KeyMap<Raw> = KeyMap<Raw>> = {
200
207
  queryKey: readonly unknown[];
201
208
  queryFn: (pageParam: unknown) => Promise<Raw[]>;
202
209
  initialPageParam: unknown;
203
- getNextPageParam: (lastPage: Message<ExtractCustom<Raw>>[], allPages: Message<ExtractCustom<Raw>>[][]) => unknown;
210
+ getNextPageParam: (lastPage: MessagePage<Raw, Map>, allPages: MessagePage<Raw, Map>[]) => unknown;
204
211
  mutationFn: (content: string) => Promise<Raw>;
205
- map: (raw: Raw) => MessageCore;
212
+ keyMap: Map;
213
+ roleResolver: (value: Raw[Map["role"]]) => MessageCore["role"];
206
214
  voice: VoiceRecognition;
207
215
  onError?: (error: unknown) => void;
208
216
  staleTime?: number;
209
217
  gcTime?: number;
210
218
  };
211
- declare function useVoiceChat<Raw extends object>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, map, voice, onError, staleTime, gcTime, }: Options<Raw>): {
212
- messages: Message<ExtractCustom<Raw>>[];
219
+ declare function useVoiceChat<Raw extends Record<string, unknown>, Map extends KeyMap<Raw>>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, keyMap, roleResolver, voice, onError, staleTime, gcTime, }: Options<Raw, Map>): {
220
+ messages: Message<Custom<Raw, Map>>[];
213
221
  isPending: boolean;
214
222
  isInitialLoading: boolean;
215
223
  startRecording: () => Promise<void>;
216
224
  stopRecording: () => void;
217
- fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<InfiniteData<Message<ExtractCustom<Raw>>[], unknown>, Error>>;
225
+ fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<_tanstack_query_core.InfiniteData<MessagePage<Raw, Map>, unknown>, Error>>;
218
226
  hasNextPage: boolean;
219
227
  isFetchingNextPage: boolean;
220
228
  };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
3
  import * as _tanstack_query_core from '@tanstack/query-core';
4
- import { InfiniteData } from '@tanstack/react-query';
5
4
 
6
5
  type ChatRole = "AI" | "USER";
7
6
  type BaseMessage = {
@@ -103,24 +102,33 @@ type CommonProps = {
103
102
  type Props<Raw> = CommonProps & (MessageProps | RawProps<Raw>);
104
103
  declare function ChatContainer<Raw>(props: Props<Raw>): react_jsx_runtime.JSX.Element;
105
104
 
106
- type ExtractCustom$1<Raw> = Omit<Raw, keyof BaseMessage>;
107
- type Options$2<Raw> = {
105
+ type KeyMap<Raw extends Record<string, unknown>> = {
106
+ id: keyof Raw;
107
+ role: keyof Raw;
108
+ content: keyof Raw;
109
+ };
110
+ type Custom<Raw extends Record<string, unknown>, Map extends KeyMap<Raw>> = Omit<Raw, Map["id" | "role" | "content"]>;
111
+
112
+ type MessagePage<Raw extends Record<string, unknown>, Map extends KeyMap<Raw>> = Message<Custom<Raw, Map>>[];
113
+
114
+ type Options$2<Raw extends Record<string, unknown>, Map extends KeyMap<Raw> = KeyMap<Raw>> = {
108
115
  queryKey: readonly unknown[];
109
116
  queryFn: (pageParam: unknown) => Promise<Raw[]>;
110
117
  initialPageParam: unknown;
111
- getNextPageParam: (lastPage: Message<ExtractCustom$1<Raw>>[], allPages: Message<ExtractCustom$1<Raw>>[][]) => unknown;
118
+ getNextPageParam: (lastPage: MessagePage<Raw, Map>, allPages: MessagePage<Raw, Map>[]) => unknown;
112
119
  mutationFn: (content: string) => Promise<Raw>;
113
- map: (raw: Raw) => MessageCore;
120
+ keyMap: Map;
121
+ roleResolver: (value: Raw[Map["role"]]) => MessageCore["role"];
114
122
  onError?: (error: unknown) => void;
115
123
  staleTime?: number;
116
124
  gcTime?: number;
117
125
  };
118
- declare function useChat<Raw extends object>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, map, onError, staleTime, gcTime, }: Options$2<Raw>): {
119
- messages: Message<ExtractCustom$1<Raw>>[];
126
+ declare function useChat<Raw extends Record<string, unknown>, Map extends KeyMap<Raw>>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, keyMap, roleResolver, onError, staleTime, gcTime, }: Options$2<Raw, Map>): {
127
+ messages: Message<Custom<Raw, Map>>[];
120
128
  sendUserMessage: (content: string) => void;
121
129
  isPending: boolean;
122
130
  isInitialLoading: boolean;
123
- fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<InfiniteData<Message<ExtractCustom$1<Raw>>[], unknown>, Error>>;
131
+ fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<_tanstack_query_core.InfiniteData<MessagePage<Raw, Map>, unknown>, Error>>;
124
132
  hasNextPage: boolean;
125
133
  isFetchingNextPage: boolean;
126
134
  };
@@ -195,26 +203,26 @@ declare function useBrowserSpeechRecognition({ lang, onStart, onEnd, onError, }?
195
203
  onTranscript: (text: string) => void;
196
204
  };
197
205
 
198
- type ExtractCustom<Raw> = Omit<Raw, keyof BaseMessage>;
199
- type Options<Raw> = {
206
+ type Options<Raw extends Record<string, unknown>, Map extends KeyMap<Raw> = KeyMap<Raw>> = {
200
207
  queryKey: readonly unknown[];
201
208
  queryFn: (pageParam: unknown) => Promise<Raw[]>;
202
209
  initialPageParam: unknown;
203
- getNextPageParam: (lastPage: Message<ExtractCustom<Raw>>[], allPages: Message<ExtractCustom<Raw>>[][]) => unknown;
210
+ getNextPageParam: (lastPage: MessagePage<Raw, Map>, allPages: MessagePage<Raw, Map>[]) => unknown;
204
211
  mutationFn: (content: string) => Promise<Raw>;
205
- map: (raw: Raw) => MessageCore;
212
+ keyMap: Map;
213
+ roleResolver: (value: Raw[Map["role"]]) => MessageCore["role"];
206
214
  voice: VoiceRecognition;
207
215
  onError?: (error: unknown) => void;
208
216
  staleTime?: number;
209
217
  gcTime?: number;
210
218
  };
211
- declare function useVoiceChat<Raw extends object>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, map, voice, onError, staleTime, gcTime, }: Options<Raw>): {
212
- messages: Message<ExtractCustom<Raw>>[];
219
+ declare function useVoiceChat<Raw extends Record<string, unknown>, Map extends KeyMap<Raw>>({ queryKey, queryFn, initialPageParam, getNextPageParam, mutationFn, keyMap, roleResolver, voice, onError, staleTime, gcTime, }: Options<Raw, Map>): {
220
+ messages: Message<Custom<Raw, Map>>[];
213
221
  isPending: boolean;
214
222
  isInitialLoading: boolean;
215
223
  startRecording: () => Promise<void>;
216
224
  stopRecording: () => void;
217
- fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<InfiniteData<Message<ExtractCustom<Raw>>[], unknown>, Error>>;
225
+ fetchNextPage: (options?: _tanstack_query_core.FetchNextPageOptions) => Promise<_tanstack_query_core.InfiniteQueryObserverResult<_tanstack_query_core.InfiniteData<MessagePage<Raw, Map>, unknown>, Error>>;
218
226
  hasNextPage: boolean;
219
227
  isFetchingNextPage: boolean;
220
228
  };
package/dist/index.js CHANGED
@@ -645,25 +645,37 @@ function ChatContainer(props) {
645
645
  // src/hooks/useChat.ts
646
646
  var import_react_query = require("@tanstack/react-query");
647
647
  var import_react6 = require("react");
648
- function splitRawToMessage(raw, mapped) {
648
+
649
+ // src/internal/messageNormalizer.ts
650
+ function buildCore(raw, map, roleResolver) {
651
+ return {
652
+ id: raw[map.id],
653
+ role: roleResolver(raw[map.role]),
654
+ content: raw[map.content]
655
+ };
656
+ }
657
+ function buildMessage(raw, map, roleResolver) {
658
+ const core = buildCore(raw, map, roleResolver);
649
659
  const custom = {};
650
- const mappedValues = new Set(Object.values(mapped));
651
- for (const [key, value] of Object.entries(raw)) {
652
- if (!mappedValues.has(value)) {
653
- custom[key] = value;
660
+ for (const key in raw) {
661
+ if (key !== map.id && key !== map.role && key !== map.content) {
662
+ custom[key] = raw[key];
654
663
  }
655
664
  }
656
- return __spreadProps(__spreadValues({}, mapped), {
665
+ return __spreadProps(__spreadValues({}, core), {
657
666
  custom
658
667
  });
659
668
  }
669
+
670
+ // src/hooks/useChat.ts
660
671
  function useChat({
661
672
  queryKey,
662
673
  queryFn,
663
674
  initialPageParam,
664
675
  getNextPageParam,
665
676
  mutationFn,
666
- map,
677
+ keyMap,
678
+ roleResolver,
667
679
  onError,
668
680
  staleTime = 0,
669
681
  gcTime = 0
@@ -680,11 +692,10 @@ function useChat({
680
692
  queryKey,
681
693
  initialPageParam,
682
694
  queryFn: async ({ pageParam }) => {
683
- const raw = await queryFn(pageParam);
684
- return raw.map((r) => {
685
- const mapped = map(r);
686
- return splitRawToMessage(r, mapped);
687
- });
695
+ const rawList = await queryFn(pageParam);
696
+ return rawList.map(
697
+ (raw) => buildMessage(raw, keyMap, roleResolver)
698
+ );
688
699
  },
689
700
  getNextPageParam,
690
701
  staleTime,
@@ -728,8 +739,7 @@ function useChat({
728
739
  return prev ? { prev } : {};
729
740
  },
730
741
  onSuccess: (rawAiResponse) => {
731
- const mapped = map(rawAiResponse);
732
- const aiMessage = splitRawToMessage(rawAiResponse, mapped);
742
+ const aiMessage = buildMessage(rawAiResponse, keyMap, roleResolver);
733
743
  queryClient.setQueryData(queryKey, (old) => {
734
744
  if (!old) return old;
735
745
  const pages = [...old.pages];
@@ -776,25 +786,14 @@ function useChat({
776
786
  // src/hooks/useVoiceChat.ts
777
787
  var import_react_query2 = require("@tanstack/react-query");
778
788
  var import_react7 = require("react");
779
- function splitRawToMessage2(raw, mapped) {
780
- const custom = {};
781
- const mappedValues = new Set(Object.values(mapped));
782
- for (const [key, value] of Object.entries(raw)) {
783
- if (!mappedValues.has(value)) {
784
- custom[key] = value;
785
- }
786
- }
787
- return __spreadProps(__spreadValues({}, mapped), {
788
- custom
789
- });
790
- }
791
789
  function useVoiceChat({
792
790
  queryKey,
793
791
  queryFn,
794
792
  initialPageParam,
795
793
  getNextPageParam,
796
794
  mutationFn,
797
- map,
795
+ keyMap,
796
+ roleResolver,
798
797
  voice,
799
798
  onError,
800
799
  staleTime = 0,
@@ -814,11 +813,10 @@ function useVoiceChat({
814
813
  queryKey,
815
814
  initialPageParam,
816
815
  queryFn: async ({ pageParam }) => {
817
- const raw = await queryFn(pageParam);
818
- return raw.map((r) => {
819
- const mapped = map(r);
820
- return splitRawToMessage2(r, mapped);
821
- });
816
+ const rawList = await queryFn(pageParam);
817
+ return rawList.map(
818
+ (raw) => buildMessage(raw, keyMap, roleResolver)
819
+ );
822
820
  },
823
821
  getNextPageParam,
824
822
  staleTime,
@@ -856,8 +854,7 @@ function useVoiceChat({
856
854
  return prev ? { prev } : {};
857
855
  },
858
856
  onSuccess: (rawAiResponse) => {
859
- const mapped = map(rawAiResponse);
860
- const aiMessage = splitRawToMessage2(rawAiResponse, mapped);
857
+ const aiMessage = buildMessage(rawAiResponse, keyMap, roleResolver);
861
858
  queryClient.setQueryData(queryKey, (old) => {
862
859
  if (!old) return old;
863
860
  const pages = [...old.pages];
package/dist/index.mjs CHANGED
@@ -604,25 +604,37 @@ function ChatContainer(props) {
604
604
  // src/hooks/useChat.ts
605
605
  import { useInfiniteQuery, useMutation, useQueryClient } from "@tanstack/react-query";
606
606
  import { useState as useState4 } from "react";
607
- function splitRawToMessage(raw, mapped) {
607
+
608
+ // src/internal/messageNormalizer.ts
609
+ function buildCore(raw, map, roleResolver) {
610
+ return {
611
+ id: raw[map.id],
612
+ role: roleResolver(raw[map.role]),
613
+ content: raw[map.content]
614
+ };
615
+ }
616
+ function buildMessage(raw, map, roleResolver) {
617
+ const core = buildCore(raw, map, roleResolver);
608
618
  const custom = {};
609
- const mappedValues = new Set(Object.values(mapped));
610
- for (const [key, value] of Object.entries(raw)) {
611
- if (!mappedValues.has(value)) {
612
- custom[key] = value;
619
+ for (const key in raw) {
620
+ if (key !== map.id && key !== map.role && key !== map.content) {
621
+ custom[key] = raw[key];
613
622
  }
614
623
  }
615
- return __spreadProps(__spreadValues({}, mapped), {
624
+ return __spreadProps(__spreadValues({}, core), {
616
625
  custom
617
626
  });
618
627
  }
628
+
629
+ // src/hooks/useChat.ts
619
630
  function useChat({
620
631
  queryKey,
621
632
  queryFn,
622
633
  initialPageParam,
623
634
  getNextPageParam,
624
635
  mutationFn,
625
- map,
636
+ keyMap,
637
+ roleResolver,
626
638
  onError,
627
639
  staleTime = 0,
628
640
  gcTime = 0
@@ -639,11 +651,10 @@ function useChat({
639
651
  queryKey,
640
652
  initialPageParam,
641
653
  queryFn: async ({ pageParam }) => {
642
- const raw = await queryFn(pageParam);
643
- return raw.map((r) => {
644
- const mapped = map(r);
645
- return splitRawToMessage(r, mapped);
646
- });
654
+ const rawList = await queryFn(pageParam);
655
+ return rawList.map(
656
+ (raw) => buildMessage(raw, keyMap, roleResolver)
657
+ );
647
658
  },
648
659
  getNextPageParam,
649
660
  staleTime,
@@ -687,8 +698,7 @@ function useChat({
687
698
  return prev ? { prev } : {};
688
699
  },
689
700
  onSuccess: (rawAiResponse) => {
690
- const mapped = map(rawAiResponse);
691
- const aiMessage = splitRawToMessage(rawAiResponse, mapped);
701
+ const aiMessage = buildMessage(rawAiResponse, keyMap, roleResolver);
692
702
  queryClient.setQueryData(queryKey, (old) => {
693
703
  if (!old) return old;
694
704
  const pages = [...old.pages];
@@ -735,25 +745,14 @@ function useChat({
735
745
  // src/hooks/useVoiceChat.ts
736
746
  import { useInfiniteQuery as useInfiniteQuery2, useMutation as useMutation2, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
737
747
  import { useEffect as useEffect4, useRef as useRef4, useState as useState5 } from "react";
738
- function splitRawToMessage2(raw, mapped) {
739
- const custom = {};
740
- const mappedValues = new Set(Object.values(mapped));
741
- for (const [key, value] of Object.entries(raw)) {
742
- if (!mappedValues.has(value)) {
743
- custom[key] = value;
744
- }
745
- }
746
- return __spreadProps(__spreadValues({}, mapped), {
747
- custom
748
- });
749
- }
750
748
  function useVoiceChat({
751
749
  queryKey,
752
750
  queryFn,
753
751
  initialPageParam,
754
752
  getNextPageParam,
755
753
  mutationFn,
756
- map,
754
+ keyMap,
755
+ roleResolver,
757
756
  voice,
758
757
  onError,
759
758
  staleTime = 0,
@@ -773,11 +772,10 @@ function useVoiceChat({
773
772
  queryKey,
774
773
  initialPageParam,
775
774
  queryFn: async ({ pageParam }) => {
776
- const raw = await queryFn(pageParam);
777
- return raw.map((r) => {
778
- const mapped = map(r);
779
- return splitRawToMessage2(r, mapped);
780
- });
775
+ const rawList = await queryFn(pageParam);
776
+ return rawList.map(
777
+ (raw) => buildMessage(raw, keyMap, roleResolver)
778
+ );
781
779
  },
782
780
  getNextPageParam,
783
781
  staleTime,
@@ -815,8 +813,7 @@ function useVoiceChat({
815
813
  return prev ? { prev } : {};
816
814
  },
817
815
  onSuccess: (rawAiResponse) => {
818
- const mapped = map(rawAiResponse);
819
- const aiMessage = splitRawToMessage2(rawAiResponse, mapped);
816
+ const aiMessage = buildMessage(rawAiResponse, keyMap, roleResolver);
820
817
  queryClient.setQueryData(queryKey, (old) => {
821
818
  if (!old) return old;
822
819
  const pages = [...old.pages];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-optimistic-chat",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",