qortex-react 0.1.0

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/README.md ADDED
@@ -0,0 +1,322 @@
1
+ # 🎭 qortex-react
2
+
3
+ > **React hooks for universal data access. Set and read data from anywhere! ⚛️**
4
+
5
+ [![npm version](https://badge.fury.io/js/qortex-react.svg)](https://badge.fury.io/js/qortex-react)
6
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/qortex-react)](https://bundlephobia.com/package/qortex-react)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
8
+ [![React](https://img.shields.io/badge/React-18+-blue.svg)](https://reactjs.org/)
9
+
10
+ ## ✨ What makes this special?
11
+
12
+ **qortex-react** lets you **set and read data from anywhere** - not just React components! Perfect for:
13
+
14
+ - 🔐 **App core data** - Authentication, user profiles accessible from anywhere
15
+ - 🔄 **Background services** - WebSocket updates, timers, external events
16
+ - 🎯 **Cross-component communication** - No more prop drilling
17
+ - ⚡ **Real-time updates** - Push changes from anywhere, see them in React instantly
18
+
19
+ ```bash
20
+ pnpm add qortex-react qortex-core
21
+ ```
22
+
23
+ ```tsx
24
+ import { queryManager, useQuery, useQueryData } from "qortex-react";
25
+
26
+ // Set global defaults for all queries
27
+ queryManager.setDefaultConfig({
28
+ staleTime: 5 * 60 * 1000, // 5 minutes default
29
+ throttleTime: 100, // 100ms throttle
30
+ usePreviousDataOnError: true
31
+ });
32
+
33
+ // Register a fetcher
34
+ queryManager.registerFetcher(["todos"], {
35
+ fetcher: async () => {
36
+ const response = await fetch("/api/todos");
37
+ return response.json();
38
+ },
39
+ placeholderData: [] // Uses global staleTime: 5 minutes
40
+ });
41
+
42
+ // Use in React component - full query state
43
+ function TodosList() {
44
+ const { data, isLoading, error, refetch } = useQuery(["todos"]);
45
+
46
+ if (isLoading) return <div>Loading...</div>;
47
+ if (error) return <div>Error: {error.message}</div>;
48
+
49
+ return (
50
+ <div>
51
+ <button onClick={() => refetch()}>Refresh</button>
52
+ <ul>
53
+ {data?.map(todo => (
54
+ <li key={todo.id}>{todo.title}</li>
55
+ ))}
56
+ </ul>
57
+ </div>
58
+ );
59
+ }
60
+
61
+ // Or just get the data - perfect for simple data access
62
+ function TodoCount() {
63
+ const todos = useQueryData(["todos"]);
64
+ return <div>Total todos: {todos?.length || 0}</div>;
65
+ }
66
+ ```
67
+
68
+ ## 🔐 Perfect for Authentication
69
+
70
+ ```tsx
71
+ // Auth service - update from anywhere
72
+ class AuthService {
73
+ async login(email: string, password: string) {
74
+ const { user, token } = await fetch("/api/auth/login", {
75
+ method: "POST",
76
+ body: JSON.stringify({ email, password })
77
+ }).then(r => r.json());
78
+
79
+ // 🎯 Update auth state - all components update automatically!
80
+ queryManager.setQueryData(["auth", "user"], user);
81
+ queryManager.setQueryData(["auth", "isAuthenticated"], true);
82
+ }
83
+
84
+ logout() {
85
+ // 🎯 Clear auth state from anywhere
86
+ queryManager.setQueryData(["auth", "user"], null);
87
+ queryManager.setQueryData(["auth", "isAuthenticated"], false);
88
+ }
89
+ }
90
+
91
+ // React components automatically reflect changes
92
+ function UserProfile() {
93
+ const { data: user } = useQuery(["auth", "user"]);
94
+ const { data: isAuthenticated } = useQuery(["auth", "isAuthenticated"]);
95
+
96
+ if (!isAuthenticated) return <div>Please log in</div>;
97
+
98
+ return (
99
+ <div>
100
+ <h2>{user?.name}</h2>
101
+ <button onClick={() => AuthService.logout()}>Logout</button>
102
+ </div>
103
+ );
104
+ }
105
+
106
+ // Or use useQueryData for simpler data access
107
+ function UserAvatar() {
108
+ const user = useQueryData(["auth", "user"]);
109
+ const isAuthenticated = useQueryData(["auth", "isAuthenticated"]);
110
+
111
+ if (!isAuthenticated) return null;
112
+
113
+ return <img src={user?.avatar} alt={user?.name} />;
114
+ }
115
+ ```
116
+
117
+ ## 🎨 API Reference
118
+
119
+ ### `useQuery(key, options?)`
120
+
121
+ Returns the full query state with loading, error, and refetch capabilities:
122
+
123
+ ```tsx
124
+ const {
125
+ data,
126
+ isLoading,
127
+ isFetching,
128
+ error,
129
+ refetch,
130
+ status,
131
+ isStale,
132
+ updatedAt
133
+ } = useQuery(key, {
134
+ refetchOnSubscribe?: "stale" | "always" | false, // Default: "stale"
135
+ enabled?: boolean, // Default: true
136
+ fetcher?: Fetcher<T>,
137
+ staleTime?: number,
138
+ placeholderData?: T
139
+ });
140
+ ```
141
+
142
+ ### `useQueryData(key, options?)`
143
+
144
+ Returns just the data - perfect for simple data access without loading states:
145
+
146
+ ```tsx
147
+ const data = useQueryData(key, {
148
+ refetchOnSubscribe?: "stale" | "always" | false, // Default: "stale"
149
+ enabled?: boolean, // Default: true
150
+ fetcher?: Fetcher<T>,
151
+ staleTime?: number,
152
+ placeholderData?: T
153
+ });
154
+
155
+ // Returns T | undefined
156
+ ```
157
+
158
+ **When to use which:**
159
+ - **`useQuery`** - When you need loading states, error handling, or refetch capabilities
160
+ - **`useQueryData`** - When you just need the data and want a simpler API
161
+
162
+ ### `queryManager.setQueryData(key, data)`
163
+
164
+ Update data from anywhere:
165
+
166
+ ```tsx
167
+ // Direct update
168
+ queryManager.setQueryData(["todos"], newTodos);
169
+
170
+ // Functional update
171
+ queryManager.setQueryData(["todos"], (oldData) => [
172
+ ...(oldData || []),
173
+ newTodo
174
+ ]);
175
+ ```
176
+
177
+ ### `queryManager.getQueryData(key)`
178
+
179
+ Read data from anywhere:
180
+
181
+ ```tsx
182
+ const user = queryManager.getQueryData(["auth", "user"]);
183
+ const isAuthenticated = queryManager.getQueryData(["auth", "isAuthenticated"]);
184
+ ```
185
+
186
+ ### `queryManager.setDefaultConfig(config)`
187
+
188
+ Set global default configuration for all queries:
189
+
190
+ ```tsx
191
+ queryManager.setDefaultConfig({
192
+ staleTime: 5 * 60 * 1000, // 5 minutes
193
+ refetchOnSubscribe: "stale",
194
+ throttleTime: 100, // 100ms throttle
195
+ usePreviousDataOnError: true,
196
+ equalityFn: shallowEqual
197
+ });
198
+ ```
199
+
200
+ **Available options:**
201
+ - `enabled?: boolean` - Whether queries are enabled by default
202
+ - `refetchOnSubscribe?: "stale" | "always" | false` - Default refetch behavior
203
+ - `staleTime?: number` - Default time before data is considered stale
204
+ - `usePreviousDataOnError?: boolean` - Keep previous data on error
205
+ - `usePlaceholderOnError?: boolean` - Use placeholder data on error
206
+ - `equalityFn?: EqualityFn<any>` - Default equality function
207
+ - `throttleTime?: number` - Default throttle time for duplicate request prevention
208
+
209
+ ## 🎯 More Examples
210
+
211
+ ### WebSocket Updates
212
+
213
+ ```tsx
214
+ // Update data from WebSocket
215
+ const ws = new WebSocket("ws://localhost:8080");
216
+ ws.onmessage = (event) => {
217
+ const data = JSON.parse(event.data);
218
+ queryManager.setQueryData(["live-stats"], data);
219
+ };
220
+
221
+ // React component automatically updates
222
+ function LiveStats() {
223
+ const { data: stats } = useQuery(["live-stats"]);
224
+ return <div>Users online: {stats?.users}</div>;
225
+ }
226
+
227
+ // Or use useQueryData for simpler access
228
+ function UserCount() {
229
+ const stats = useQueryData(["live-stats"]);
230
+ return <span>{stats?.users || 0}</span>;
231
+ }
232
+ ```
233
+
234
+ ### Cross-Component Communication
235
+
236
+ ```tsx
237
+ // Component A updates data
238
+ function UserActions({ userId }) {
239
+ const updateStatus = (status) => {
240
+ queryManager.setQueryData(["user", userId], (user) => ({
241
+ ...user,
242
+ status
243
+ }));
244
+ };
245
+
246
+ return (
247
+ <div>
248
+ <button onClick={() => updateStatus("online")}>Set Online</button>
249
+ </div>
250
+ );
251
+ }
252
+
253
+ // Component B automatically reflects changes
254
+ function UserStatus({ userId }) {
255
+ const { data: user } = useQuery(["user", userId]);
256
+ return <div>Status: {user?.status}</div>;
257
+ }
258
+
259
+ // Or use useQueryData for simpler data access
260
+ function UserName({ userId }) {
261
+ const user = useQueryData(["user", userId]);
262
+ return <span>{user?.name}</span>;
263
+ }
264
+ ```
265
+
266
+ ## 🎭 TypeScript Support
267
+
268
+ ```tsx
269
+ interface User {
270
+ id: string;
271
+ name: string;
272
+ email: string;
273
+ }
274
+
275
+ // Type-safe usage
276
+ queryManager.registerFetcher<User[]>(["users"], {
277
+ fetcher: async (): Promise<User[]> => {
278
+ const response = await fetch("/api/users");
279
+ return response.json();
280
+ }
281
+ });
282
+
283
+ function UsersList() {
284
+ const { data: users, isLoading, error } = useQuery<User[]>(["users"]);
285
+
286
+ if (isLoading) return <div>Loading...</div>;
287
+ if (error) return <div>Error: {error.message}</div>;
288
+
289
+ return (
290
+ <ul>
291
+ {users?.map(user => (
292
+ <li key={user.id}>{user.name} - {user.email}</li>
293
+ ))}
294
+ </ul>
295
+ );
296
+ }
297
+
298
+ // Or use useQueryData for simpler typed access
299
+ function UserCount() {
300
+ const users = useQueryData<User[]>(["users"]);
301
+ return <div>Total users: {users?.length || 0}</div>;
302
+ }
303
+ ```
304
+
305
+ ## 📄 License
306
+
307
+ MIT License - feel free to use this in your projects! 🎉
308
+
309
+ ## 🎯 Support
310
+
311
+ Need help? Have questions?
312
+
313
+ - 📧 **Email**: [darshannaik.com](https://darshannaik.com)
314
+ - 🐛 **Issues**: [GitHub Issues](https://github.com/Darshan-Naik/qortex/issues)
315
+ - 🌟 **Repository**: [https://github.com/Darshan-Naik/qortex](https://github.com/Darshan-Naik/qortex)
316
+
317
+ ---
318
+
319
+ <div align="center">
320
+ <p>Made with ❤️ by <a href="https://darshannaik.com">Darshan</a></p>
321
+ <p>⭐ Star this repo if you found it helpful!</p>
322
+ </div>
package/index.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import { Fetcher, QueryKey, QueryOptions, InferFetcherReturnType, QueryState } from 'qortex-core';
2
+ export * from 'qortex-core';
3
+
4
+ /**
5
+ * useQuery hook for React integration with qortex
6
+ * Provides reactive data fetching with automatic re-renders on state changes
7
+ * Enhanced with automatic type inference from fetchers
8
+ */
9
+ declare function useQuery<F extends Fetcher>(key: QueryKey, opts: QueryOptions<InferFetcherReturnType<F>> & {
10
+ fetcher: F;
11
+ }): QueryState<InferFetcherReturnType<F>>;
12
+ declare function useQuery<T = any>(key: QueryKey, opts?: QueryOptions<T>): QueryState<T>;
13
+
14
+ /**
15
+ * useQueryData hook for React integration with qortex
16
+ * Provides reactive data fetching with automatic re-renders on state changes
17
+ * Enhanced with automatic type inference from fetchers
18
+ */
19
+ declare function useQueryData<F extends Fetcher>(key: QueryKey, opts: QueryOptions<InferFetcherReturnType<F>> & {
20
+ fetcher: F;
21
+ }): InferFetcherReturnType<F> | undefined;
22
+ declare function useQueryData<T = any>(key: QueryKey, opts?: QueryOptions<T>): T | undefined;
23
+
24
+ export { useQuery, useQueryData };
package/index.js ADDED
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.ts
22
+ var src_exports = {};
23
+ __export(src_exports, {
24
+ useQuery: () => useQuery,
25
+ useQueryData: () => useQueryData
26
+ });
27
+ module.exports = __toCommonJS(src_exports);
28
+ __reExport(src_exports, require("qortex-core"), module.exports);
29
+
30
+ // src/useQuery.tsx
31
+ var import_react = require("react");
32
+ var import_qortex_core = require("qortex-core");
33
+ function useQuery(key, opts) {
34
+ const serializedKey = (0, import_qortex_core.serializeKey)(key);
35
+ const getSnapshot = (0, import_react.useCallback)(() => {
36
+ return import_qortex_core.queryManager.getQueryState(key, opts);
37
+ }, [serializedKey]);
38
+ const subscribe = (0, import_react.useCallback)((callback) => {
39
+ return import_qortex_core.queryManager.subscribeQuery(key, callback, opts);
40
+ }, [serializedKey]);
41
+ const state = (0, import_react.useSyncExternalStore)(
42
+ subscribe,
43
+ getSnapshot
44
+ );
45
+ return state;
46
+ }
47
+
48
+ // src/useQueryData.tsx
49
+ var import_react2 = require("react");
50
+ var import_qortex_core2 = require("qortex-core");
51
+ function useQueryData(key, opts) {
52
+ const serializedKey = (0, import_qortex_core2.serializeKey)(key);
53
+ const getSnapshot = (0, import_react2.useCallback)(() => {
54
+ return import_qortex_core2.queryManager.getQueryData(key, opts);
55
+ }, [serializedKey]);
56
+ const subscribe = (0, import_react2.useCallback)((callback) => {
57
+ return import_qortex_core2.queryManager.subscribeQuery(key, callback, opts);
58
+ }, [serializedKey]);
59
+ const data = (0, import_react2.useSyncExternalStore)(
60
+ subscribe,
61
+ getSnapshot
62
+ );
63
+ return data;
64
+ }
65
+ // Annotate the CommonJS export names for ESM import in node:
66
+ 0 && (module.exports = {
67
+ useQuery,
68
+ useQueryData,
69
+ ...require("qortex-core")
70
+ });
package/index.mjs ADDED
@@ -0,0 +1,42 @@
1
+ // src/index.ts
2
+ export * from "qortex-core";
3
+
4
+ // src/useQuery.tsx
5
+ import { useSyncExternalStore, useCallback } from "react";
6
+ import { queryManager, serializeKey } from "qortex-core";
7
+ function useQuery(key, opts) {
8
+ const serializedKey = serializeKey(key);
9
+ const getSnapshot = useCallback(() => {
10
+ return queryManager.getQueryState(key, opts);
11
+ }, [serializedKey]);
12
+ const subscribe = useCallback((callback) => {
13
+ return queryManager.subscribeQuery(key, callback, opts);
14
+ }, [serializedKey]);
15
+ const state = useSyncExternalStore(
16
+ subscribe,
17
+ getSnapshot
18
+ );
19
+ return state;
20
+ }
21
+
22
+ // src/useQueryData.tsx
23
+ import { useSyncExternalStore as useSyncExternalStore2, useCallback as useCallback2 } from "react";
24
+ import { queryManager as queryManager2, serializeKey as serializeKey2 } from "qortex-core";
25
+ function useQueryData(key, opts) {
26
+ const serializedKey = serializeKey2(key);
27
+ const getSnapshot = useCallback2(() => {
28
+ return queryManager2.getQueryData(key, opts);
29
+ }, [serializedKey]);
30
+ const subscribe = useCallback2((callback) => {
31
+ return queryManager2.subscribeQuery(key, callback, opts);
32
+ }, [serializedKey]);
33
+ const data = useSyncExternalStore2(
34
+ subscribe,
35
+ getSnapshot
36
+ );
37
+ return data;
38
+ }
39
+ export {
40
+ useQuery,
41
+ useQueryData
42
+ };
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "qortex-react",
3
+ "version": "0.1.0",
4
+ "description": "React hook bridge for qortex runtime",
5
+ "main": "index.js",
6
+ "module": "index.mjs",
7
+ "types": "index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./index.d.ts",
11
+ "import": "./index.mjs",
12
+ "require": "./index.js"
13
+ }
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "files": [
19
+ "index.js",
20
+ "index.mjs",
21
+ "index.d.ts",
22
+ "README.md"
23
+ ],
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/Darshan-Naik/qortex.git"
27
+ },
28
+ "homepage": "https://github.com/Darshan-Naik/qortex#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/Darshan-Naik/qortex/issues"
31
+ },
32
+ "keywords": [
33
+ "qortex",
34
+ "react",
35
+ "useQuery",
36
+ "cache",
37
+ "mfe",
38
+ "data-fetching",
39
+ "typescript"
40
+ ],
41
+ "author": "Darshan Naik",
42
+ "license": "MIT",
43
+ "dependencies": {
44
+ "qortex-core": "0.1.0"
45
+ },
46
+ "peerDependencies": {
47
+ "react": ">=18"
48
+ }
49
+ }