Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@magicul/react-chat-stream

Package Overview
Dependencies
Maintainers
2
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@magicul/react-chat-stream - npm Package Compare versions

Comparing version 0.2.3 to 0.3.0

.eslintignore

35

dist/hooks/useChatStream.d.ts

@@ -1,33 +0,14 @@

import { ChangeEvent, Dispatch, FormEvent, SetStateAction } from 'react';
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
type ChatMessage = {
role: 'bot' | 'user';
content: string;
id: string;
};
export type UseChatStreamOptions = {
url: string;
method: HttpMethod;
query?: Record<string, string>;
headers?: HeadersInit;
body?: Record<string, string>;
};
export type UseChatStreamInputMethod = {
type: 'body' | 'query';
key: string;
};
type UseChatStreamInput = {
options: UseChatStreamOptions;
method: UseChatStreamInputMethod;
};
import { ChangeEvent, FormEvent } from 'react';
import { UseChatStreamChatMessage, UseChatStreamInput } from '../types';
declare const useChatStream: (input: UseChatStreamInput) => {
messages: ChatMessage[];
setMessages: Dispatch<SetStateAction<ChatMessage[]>>;
messages: UseChatStreamChatMessage[];
setMessages: import("react").Dispatch<import("react").SetStateAction<UseChatStreamChatMessage[]>>;
input: string;
setInput: Dispatch<SetStateAction<string>>;
setInput: import("react").Dispatch<import("react").SetStateAction<string>>;
handleInputChange: (e: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement>) => void;
handleSubmit: (e?: FormEvent<HTMLFormElement>, newMessage?: string) => Promise<void>;
isLoading: boolean;
handleSubmit: (e?: FormEvent<HTMLFormElement>) => Promise<void>;
submitMessage: (message: string) => Promise<void>;
isStreaming: boolean;
};
export default useChatStream;
//# sourceMappingURL=useChatStream.d.ts.map

@@ -68,14 +68,26 @@ "use strict";

var streams_1 = require("../utils/streams");
var uuid_1 = require("uuid");
var BOT_ERROR_MESSAGE = 'Something went wrong fetching AI response.';
var useChatStream = function (input) {
var _a = (0, react_1.useState)([]), messages = _a[0], setMessages = _a[1];
var _b = (0, react_1.useState)(''), message = _b[0], setMessage = _b[1];
var _c = (0, react_1.useState)(false), isLoading = _c[0], setIsLoading = _c[1];
var _b = (0, react_1.useState)(''), formInput = _b[0], setFormInput = _b[1];
var _c = (0, react_1.useState)(false), isStreaming = _c[0], setIsStreaming = _c[1];
var handleInputChange = function (e) {
setMessage(e.target.value);
setFormInput(e.target.value);
};
var addMessageToChat = function (message, role) {
if (role === void 0) { role = 'user'; }
setMessages(function (messages) { return __spreadArray(__spreadArray([], messages, true), [{ role: role, content: message, id: (0, uuid_1.v4)() }], false); });
var handleSubmit = function (e) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
e === null || e === void 0 ? void 0 : e.preventDefault();
return [4 /*yield*/, resetInputAndGetResponse()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); };
var addMessage = function (message) {
var messageWithId = __assign(__assign({}, message), { id: crypto.randomUUID() });
setMessages(function (messages) { return __spreadArray(__spreadArray([], messages, true), [messageWithId], false); });
return messageWithId;
};

@@ -91,3 +103,3 @@ var appendMessageToChat = function (message) {

var fetchAndUpdateAIResponse = function (message) { return __awaiter(void 0, void 0, void 0, function () {
var stream, _a, _b, _c, message_1, e_1_1;
var stream, initialMessage, response, _a, _b, _c, message_1, e_1_1;
var _d, e_1, _e, _f;

@@ -99,5 +111,4 @@ return __generator(this, function (_g) {

stream = _g.sent();
if (!stream)
throw new Error();
addMessageToChat('', 'bot');
initialMessage = addMessage({ content: '', role: 'bot' });
response = '';
_g.label = 2;

@@ -115,2 +126,3 @@ case 2:

appendMessageToChat(message_1);
response += message_1;
_g.label = 5;

@@ -137,29 +149,42 @@ case 5:

case 12: return [7 /*endfinally*/];
case 13: return [2 /*return*/];
case 13: return [2 /*return*/, __assign(__assign({}, initialMessage), { content: response })];
}
});
}); };
var handleSubmit = function (e, newMessage) { return __awaiter(void 0, void 0, void 0, function () {
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
var submitMessage = function (message) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/, resetInputAndGetResponse(message)];
}); }); };
var resetInputAndGetResponse = function (message) { return __awaiter(void 0, void 0, void 0, function () {
var addedMessage, addedMessage_1, _a, addedMessage_2;
var _b, _c, _d, _e, _f, _g;
return __generator(this, function (_h) {
switch (_h.label) {
case 0:
setIsLoading(true);
e === null || e === void 0 ? void 0 : e.preventDefault();
addMessageToChat(newMessage !== null && newMessage !== void 0 ? newMessage : message);
setMessage('');
_b.label = 1;
setIsStreaming(true);
addedMessage = addMessage({ content: message !== null && message !== void 0 ? message : formInput, role: 'user' });
return [4 /*yield*/, ((_c = (_b = input.handlers).onMessageAdded) === null || _c === void 0 ? void 0 : _c.call(_b, addedMessage))];
case 1:
_b.trys.push([1, 3, , 4]);
return [4 /*yield*/, fetchAndUpdateAIResponse(newMessage !== null && newMessage !== void 0 ? newMessage : message)];
_h.sent();
setFormInput('');
_h.label = 2;
case 2:
_b.sent();
return [3 /*break*/, 4];
_h.trys.push([2, 5, 7, 8]);
return [4 /*yield*/, fetchAndUpdateAIResponse(formInput)];
case 3:
_a = _b.sent();
addMessageToChat(BOT_ERROR_MESSAGE, 'bot');
return [3 /*break*/, 4];
addedMessage_1 = _h.sent();
return [4 /*yield*/, ((_e = (_d = input.handlers).onMessageAdded) === null || _e === void 0 ? void 0 : _e.call(_d, addedMessage_1))];
case 4:
setIsLoading(false);
return [2 /*return*/];
_h.sent();
return [3 /*break*/, 8];
case 5:
_a = _h.sent();
addedMessage_2 = addMessage({ content: BOT_ERROR_MESSAGE, role: 'bot' });
return [4 /*yield*/, ((_g = (_f = input.handlers).onMessageAdded) === null || _g === void 0 ? void 0 : _g.call(_f, addedMessage_2))];
case 6:
_h.sent();
return [3 /*break*/, 8];
case 7:
setIsStreaming(false);
return [7 /*endfinally*/];
case 8: return [2 /*return*/];
}

@@ -171,7 +196,8 @@ });

setMessages: setMessages,
input: message,
setInput: setMessage,
input: formInput,
setInput: setFormInput,
handleInputChange: handleInputChange,
handleSubmit: handleSubmit,
isLoading: isLoading,
submitMessage: submitMessage,
isStreaming: isStreaming,
};

@@ -178,0 +204,0 @@ };

import useChatStream from './hooks/useChatStream';
export * from './types';
export default useChatStream;
//# sourceMappingURL=index.d.ts.map
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -7,3 +21,4 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

var useChatStream_1 = __importDefault(require("./hooks/useChatStream"));
__exportStar(require("./types"), exports);
exports.default = useChatStream_1.default;
//# sourceMappingURL=index.js.map

@@ -1,4 +0,4 @@

import type { UseChatStreamInputMethod, UseChatStreamOptions } from '../hooks/useChatStream';
export declare const getStream: (input: string, options: UseChatStreamOptions, method: UseChatStreamInputMethod) => Promise<ReadableStream<Uint8Array> | null>;
import { UseChatStreamHttpOptions, UseChatStreamInputMethod } from '../types';
export declare const getStream: (input: string, options: UseChatStreamHttpOptions, method: UseChatStreamInputMethod) => Promise<ReadableStream<Uint8Array> | null>;
export declare function decodeStreamToJson(data: ReadableStream<Uint8Array> | null): AsyncIterableIterator<string>;
//# sourceMappingURL=streams.d.ts.map

@@ -53,4 +53,5 @@ "use strict";

var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
return i = {}, verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }

@@ -80,3 +81,2 @@ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }

params = '?' + new URLSearchParams(options.query).toString();
console.log(JSON.stringify(options.body, function (_k, v) { return v === null ? undefined : v; }));
return [4 /*yield*/, fetch(options.url + params, {

@@ -83,0 +83,0 @@ method: options.method,

{
"name": "@magicul/react-chat-stream",
"description": "A React hook that lets you easily integrate your custom ChatGPT-like chat in React.",
"version": "0.2.3",
"version": "0.3.0",
"main": "dist/index.js",

@@ -35,20 +35,18 @@ "types": "dist/index.d.ts",

"devDependencies": {
"@types/react": "^18.2.14",
"@typescript-eslint/eslint-plugin": "^5.59.11",
"@typescript-eslint/parser": "^5.61.0",
"eslint": "8.46.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"prettier": "^3.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^5.1.6"
},
"dependencies": {
"uuid": "^9.0.0",
"@types/uuid": "^9.0.2"
"@types/react": "18.2.56",
"@typescript-eslint/eslint-plugin": "7.0.1",
"@typescript-eslint/parser": "7.0.1",
"eslint": "8.56.0",
"eslint-config-airbnb": "19.0.4",
"eslint-config-next": "14.1.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-jsx-a11y": "6.8.0",
"eslint-plugin-prettier": "5.1.3",
"eslint-plugin-react": "7.33.2",
"prettier": "3.2.5",
"react": "18.2.0",
"react-dom": "18.2.0",
"typescript": "5.3.3"
}
}

@@ -1,46 +0,28 @@

import { ChangeEvent, Dispatch, FormEvent, SetStateAction, useState } from 'react';
import { ChangeEvent, FormEvent, useState } from 'react';
import { decodeStreamToJson, getStream } from '../utils/streams';
import { v4 as uuidv4 } from 'uuid';
import { UseChatStreamChatMessage, UseChatStreamInput } from '../types';
const BOT_ERROR_MESSAGE = 'Something went wrong fetching AI response.';
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
type ChatMessage = {
role: 'bot' | 'user';
content: string;
id: string;
}
export type UseChatStreamOptions = {
url: string;
method: HttpMethod;
query?: Record<string, string>;
headers?: HeadersInit;
body?: Record<string, string>;
}
export type UseChatStreamInputMethod = {
type: 'body' | 'query',
key: string;
}
type UseChatStreamInput = {
options: UseChatStreamOptions,
method: UseChatStreamInputMethod,
};
const useChatStream = (input: UseChatStreamInput) => {
const [messages, setMessages] = useState<ChatMessage[]>([]);
const [message, setMessage] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [messages, setMessages] = useState<UseChatStreamChatMessage[]>([]);
const [formInput, setFormInput] = useState('');
const [isStreaming, setIsStreaming] = useState(false);
const handleInputChange = (e: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement>) => {
setMessage(e.target.value);
setFormInput(e.target.value);
};
const addMessageToChat = (message: string, role: ChatMessage['role'] = 'user') => {
setMessages(messages => [...messages, { role, content: message, id: uuidv4() }]);
const handleSubmit = async (e?: FormEvent<HTMLFormElement>) => {
e?.preventDefault();
await resetInputAndGetResponse();
};
const addMessage = (message: Omit<UseChatStreamChatMessage, 'id'>) => {
const messageWithId = { ...message, id: crypto.randomUUID() as string };
setMessages(messages => [...messages, messageWithId]);
return messageWithId;
};
const appendMessageToChat = (message: string) => {

@@ -59,34 +41,41 @@ setMessages(messages => {

const stream = await getStream(message, input.options, input.method);
if (!stream) throw new Error();
const initialMessage = addMessage({ content: '', role: 'bot' });
let response = '';
addMessageToChat('', 'bot');
for await (const message of decodeStreamToJson(stream)) {
appendMessageToChat(message);
response += message;
}
return { ...initialMessage, content: response };
};
const handleSubmit = async (e?: FormEvent<HTMLFormElement>, newMessage?: string) => {
setIsLoading(true);
e?.preventDefault();
addMessageToChat(newMessage ?? message);
setMessage('');
const submitMessage = async (message: string) => resetInputAndGetResponse(message);
const resetInputAndGetResponse = async (message?: string) => {
setIsStreaming(true);
const addedMessage = addMessage({ content: message ?? formInput, role: 'user' });
await input.handlers.onMessageAdded?.(addedMessage);
setFormInput('');
try {
await fetchAndUpdateAIResponse(newMessage ?? message);
const addedMessage = await fetchAndUpdateAIResponse(formInput);
await input.handlers.onMessageAdded?.(addedMessage);
} catch {
addMessageToChat(BOT_ERROR_MESSAGE, 'bot');
const addedMessage = addMessage({ content: BOT_ERROR_MESSAGE, role: 'bot' });
await input.handlers.onMessageAdded?.(addedMessage);
} finally {
setIsStreaming(false);
}
}
setIsLoading(false);
};
return {
messages,
setMessages,
input: message,
setInput: setMessage,
input: formInput,
setInput: setFormInput,
handleInputChange,
handleSubmit,
isLoading,
submitMessage,
isStreaming,
};

@@ -93,0 +82,0 @@ };

import useChatStream from './hooks/useChatStream';
export * from './types';
export default useChatStream;

@@ -1,5 +0,2 @@

import type {
UseChatStreamInputMethod,
UseChatStreamOptions
} from '../hooks/useChatStream';
import { UseChatStreamHttpOptions, UseChatStreamInputMethod } from '../types';

@@ -10,3 +7,3 @@ const DEFAULT_HEADERS = {

const mergeInputInOptions = (input: string, options: UseChatStreamOptions, method: UseChatStreamInputMethod) => {
const mergeInputInOptions = (input: string, options: UseChatStreamHttpOptions, method: UseChatStreamInputMethod) => {
options.query = options.query ?? {};

@@ -18,14 +15,10 @@ (options[method.type] as Record<string, unknown>)[method.key] = input;

export const getStream = async (input: string, options: UseChatStreamOptions, method: UseChatStreamInputMethod) => {
export const getStream = async (input: string, options: UseChatStreamHttpOptions, method: UseChatStreamInputMethod) => {
options = mergeInputInOptions(input, options, method);
const params = '?' + new URLSearchParams(options.query).toString();
console.log(JSON.stringify(options.body, (_k, v) => v === null ? undefined : v));
const response = await fetch(options.url + params, {
method: options.method,
headers: {
...DEFAULT_HEADERS,
...options.headers
},
headers: { ...DEFAULT_HEADERS, ...options.headers },
body: JSON.stringify(options.body, (_k, v) => v === null ? undefined : v)

@@ -32,0 +25,0 @@ });

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc