@nimbleflux/fluxbase-sdk-react 2026.3.6-rc.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/.nvmrc +1 -0
- package/README-ADMIN.md +1076 -0
- package/README.md +195 -0
- package/examples/AdminDashboard.tsx +513 -0
- package/examples/README.md +163 -0
- package/package.json +66 -0
- package/src/context.test.tsx +147 -0
- package/src/context.tsx +33 -0
- package/src/index.test.ts +255 -0
- package/src/index.ts +175 -0
- package/src/test-setup.ts +22 -0
- package/src/test-utils.tsx +215 -0
- package/src/use-admin-auth.test.ts +175 -0
- package/src/use-admin-auth.ts +187 -0
- package/src/use-admin-hooks.test.ts +457 -0
- package/src/use-admin-hooks.ts +309 -0
- package/src/use-auth-config.test.ts +145 -0
- package/src/use-auth-config.ts +101 -0
- package/src/use-auth.test.ts +313 -0
- package/src/use-auth.ts +164 -0
- package/src/use-captcha.test.ts +273 -0
- package/src/use-captcha.ts +250 -0
- package/src/use-client-keys.test.ts +286 -0
- package/src/use-client-keys.ts +185 -0
- package/src/use-graphql.test.ts +424 -0
- package/src/use-graphql.ts +392 -0
- package/src/use-query.test.ts +348 -0
- package/src/use-query.ts +211 -0
- package/src/use-realtime.test.ts +359 -0
- package/src/use-realtime.ts +180 -0
- package/src/use-saml.test.ts +269 -0
- package/src/use-saml.ts +221 -0
- package/src/use-storage.test.ts +549 -0
- package/src/use-storage.ts +508 -0
- package/src/use-table-export.ts +481 -0
- package/src/use-users.test.ts +264 -0
- package/src/use-users.ts +198 -0
- package/tsconfig.json +28 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/tsup.config.ts +11 -0
- package/typedoc.json +33 -0
- package/vitest.config.ts +22 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for users management hook
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
6
|
+
import { renderHook, waitFor, act } from '@testing-library/react';
|
|
7
|
+
import { useUsers } from './use-users';
|
|
8
|
+
import { createMockClient, createWrapper } from './test-utils';
|
|
9
|
+
|
|
10
|
+
describe('useUsers', () => {
|
|
11
|
+
it('should fetch users on mount when autoFetch is true', async () => {
|
|
12
|
+
const mockUsers = [
|
|
13
|
+
{ id: '1', email: 'user1@example.com', role: 'user' },
|
|
14
|
+
{ id: '2', email: 'user2@example.com', role: 'admin' },
|
|
15
|
+
];
|
|
16
|
+
const listUsersMock = vi.fn().mockResolvedValue({
|
|
17
|
+
data: { users: mockUsers, total: 2 },
|
|
18
|
+
error: null,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const client = createMockClient({
|
|
22
|
+
admin: { listUsers: listUsersMock },
|
|
23
|
+
} as any);
|
|
24
|
+
|
|
25
|
+
const { result } = renderHook(
|
|
26
|
+
() => useUsers({ autoFetch: true }),
|
|
27
|
+
{ wrapper: createWrapper(client) }
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
await waitFor(() => expect(result.current.isLoading).toBe(false));
|
|
31
|
+
expect(result.current.users).toEqual(mockUsers);
|
|
32
|
+
expect(result.current.total).toBe(2);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should not fetch users when autoFetch is false', async () => {
|
|
36
|
+
const listUsersMock = vi.fn();
|
|
37
|
+
|
|
38
|
+
const client = createMockClient({
|
|
39
|
+
admin: { listUsers: listUsersMock },
|
|
40
|
+
} as any);
|
|
41
|
+
|
|
42
|
+
const { result } = renderHook(
|
|
43
|
+
() => useUsers({ autoFetch: false }),
|
|
44
|
+
{ wrapper: createWrapper(client) }
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
await waitFor(() => expect(result.current.isLoading).toBe(false));
|
|
48
|
+
expect(listUsersMock).not.toHaveBeenCalled();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should pass list options', async () => {
|
|
52
|
+
const listUsersMock = vi.fn().mockResolvedValue({
|
|
53
|
+
data: { users: [], total: 0 },
|
|
54
|
+
error: null,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const client = createMockClient({
|
|
58
|
+
admin: { listUsers: listUsersMock },
|
|
59
|
+
} as any);
|
|
60
|
+
|
|
61
|
+
renderHook(
|
|
62
|
+
() => useUsers({ autoFetch: true, limit: 10, search: 'test' }),
|
|
63
|
+
{ wrapper: createWrapper(client) }
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
await waitFor(() => {
|
|
67
|
+
expect(listUsersMock).toHaveBeenCalledWith(
|
|
68
|
+
expect.objectContaining({ limit: 10, search: 'test' })
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should invite user', async () => {
|
|
74
|
+
const listUsersMock = vi.fn().mockResolvedValue({
|
|
75
|
+
data: { users: [], total: 0 },
|
|
76
|
+
error: null,
|
|
77
|
+
});
|
|
78
|
+
const inviteUserMock = vi.fn().mockResolvedValue({ data: {}, error: null });
|
|
79
|
+
|
|
80
|
+
const client = createMockClient({
|
|
81
|
+
admin: {
|
|
82
|
+
listUsers: listUsersMock,
|
|
83
|
+
inviteUser: inviteUserMock,
|
|
84
|
+
},
|
|
85
|
+
} as any);
|
|
86
|
+
|
|
87
|
+
const { result } = renderHook(
|
|
88
|
+
() => useUsers({ autoFetch: true }),
|
|
89
|
+
{ wrapper: createWrapper(client) }
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
await waitFor(() => expect(result.current.isLoading).toBe(false));
|
|
93
|
+
|
|
94
|
+
await act(async () => {
|
|
95
|
+
await result.current.inviteUser('new@example.com', 'user');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
expect(inviteUserMock).toHaveBeenCalledWith({ email: 'new@example.com', role: 'user' });
|
|
99
|
+
// Should refetch after invite
|
|
100
|
+
expect(listUsersMock).toHaveBeenCalledTimes(2);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should update user role', async () => {
|
|
104
|
+
const listUsersMock = vi.fn().mockResolvedValue({
|
|
105
|
+
data: { users: [], total: 0 },
|
|
106
|
+
error: null,
|
|
107
|
+
});
|
|
108
|
+
const updateUserRoleMock = vi.fn().mockResolvedValue({ data: {}, error: null });
|
|
109
|
+
|
|
110
|
+
const client = createMockClient({
|
|
111
|
+
admin: {
|
|
112
|
+
listUsers: listUsersMock,
|
|
113
|
+
updateUserRole: updateUserRoleMock,
|
|
114
|
+
},
|
|
115
|
+
} as any);
|
|
116
|
+
|
|
117
|
+
const { result } = renderHook(
|
|
118
|
+
() => useUsers({ autoFetch: true }),
|
|
119
|
+
{ wrapper: createWrapper(client) }
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
await waitFor(() => expect(result.current.isLoading).toBe(false));
|
|
123
|
+
|
|
124
|
+
await act(async () => {
|
|
125
|
+
await result.current.updateUserRole('1', 'admin');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
expect(updateUserRoleMock).toHaveBeenCalledWith('1', 'admin');
|
|
129
|
+
// Should refetch after update
|
|
130
|
+
expect(listUsersMock).toHaveBeenCalledTimes(2);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should delete user', async () => {
|
|
134
|
+
const listUsersMock = vi.fn().mockResolvedValue({
|
|
135
|
+
data: { users: [], total: 0 },
|
|
136
|
+
error: null,
|
|
137
|
+
});
|
|
138
|
+
const deleteUserMock = vi.fn().mockResolvedValue({ data: {}, error: null });
|
|
139
|
+
|
|
140
|
+
const client = createMockClient({
|
|
141
|
+
admin: {
|
|
142
|
+
listUsers: listUsersMock,
|
|
143
|
+
deleteUser: deleteUserMock,
|
|
144
|
+
},
|
|
145
|
+
} as any);
|
|
146
|
+
|
|
147
|
+
const { result } = renderHook(
|
|
148
|
+
() => useUsers({ autoFetch: true }),
|
|
149
|
+
{ wrapper: createWrapper(client) }
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
await waitFor(() => expect(result.current.isLoading).toBe(false));
|
|
153
|
+
|
|
154
|
+
await act(async () => {
|
|
155
|
+
await result.current.deleteUser('1');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
expect(deleteUserMock).toHaveBeenCalledWith('1');
|
|
159
|
+
// Should refetch after delete
|
|
160
|
+
expect(listUsersMock).toHaveBeenCalledTimes(2);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should reset user password', async () => {
|
|
164
|
+
const listUsersMock = vi.fn().mockResolvedValue({
|
|
165
|
+
data: { users: [], total: 0 },
|
|
166
|
+
error: null,
|
|
167
|
+
});
|
|
168
|
+
const resetPasswordMock = vi.fn().mockResolvedValue({
|
|
169
|
+
data: { message: 'Password reset email sent' },
|
|
170
|
+
error: null,
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const client = createMockClient({
|
|
174
|
+
admin: {
|
|
175
|
+
listUsers: listUsersMock,
|
|
176
|
+
resetUserPassword: resetPasswordMock,
|
|
177
|
+
},
|
|
178
|
+
} as any);
|
|
179
|
+
|
|
180
|
+
const { result } = renderHook(
|
|
181
|
+
() => useUsers({ autoFetch: true }),
|
|
182
|
+
{ wrapper: createWrapper(client) }
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
await waitFor(() => expect(result.current.isLoading).toBe(false));
|
|
186
|
+
|
|
187
|
+
let response;
|
|
188
|
+
await act(async () => {
|
|
189
|
+
response = await result.current.resetPassword('1');
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
expect(resetPasswordMock).toHaveBeenCalledWith('1');
|
|
193
|
+
expect(response).toEqual({ message: 'Password reset email sent' });
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('should handle fetch error', async () => {
|
|
197
|
+
const error = new Error('Failed to fetch');
|
|
198
|
+
const listUsersMock = vi.fn().mockResolvedValue({ data: null, error });
|
|
199
|
+
|
|
200
|
+
const client = createMockClient({
|
|
201
|
+
admin: { listUsers: listUsersMock },
|
|
202
|
+
} as any);
|
|
203
|
+
|
|
204
|
+
const { result } = renderHook(
|
|
205
|
+
() => useUsers({ autoFetch: true }),
|
|
206
|
+
{ wrapper: createWrapper(client) }
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
await waitFor(() => expect(result.current.isLoading).toBe(false));
|
|
210
|
+
expect(result.current.error).toBe(error);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('should set up refetch interval', async () => {
|
|
214
|
+
vi.useFakeTimers();
|
|
215
|
+
const listUsersMock = vi.fn().mockResolvedValue({
|
|
216
|
+
data: { users: [], total: 0 },
|
|
217
|
+
error: null,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
const client = createMockClient({
|
|
221
|
+
admin: { listUsers: listUsersMock },
|
|
222
|
+
} as any);
|
|
223
|
+
|
|
224
|
+
const { unmount } = renderHook(
|
|
225
|
+
() => useUsers({ autoFetch: true, refetchInterval: 5000 }),
|
|
226
|
+
{ wrapper: createWrapper(client) }
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
// Initial fetch
|
|
230
|
+
expect(listUsersMock).toHaveBeenCalledTimes(1);
|
|
231
|
+
|
|
232
|
+
// Advance timer
|
|
233
|
+
await act(async () => {
|
|
234
|
+
vi.advanceTimersByTime(5000);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
expect(listUsersMock).toHaveBeenCalledTimes(2);
|
|
238
|
+
|
|
239
|
+
unmount();
|
|
240
|
+
vi.useRealTimers();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('should refetch on demand', async () => {
|
|
244
|
+
const listUsersMock = vi.fn().mockResolvedValue({
|
|
245
|
+
data: { users: [], total: 0 },
|
|
246
|
+
error: null,
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
const client = createMockClient({
|
|
250
|
+
admin: { listUsers: listUsersMock },
|
|
251
|
+
} as any);
|
|
252
|
+
|
|
253
|
+
const { result } = renderHook(
|
|
254
|
+
() => useUsers({ autoFetch: false }),
|
|
255
|
+
{ wrapper: createWrapper(client) }
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
await act(async () => {
|
|
259
|
+
await result.current.refetch();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
expect(listUsersMock).toHaveBeenCalledTimes(1);
|
|
263
|
+
});
|
|
264
|
+
});
|
package/src/use-users.ts
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react'
|
|
2
|
+
import { useFluxbaseClient } from './context'
|
|
3
|
+
import type { EnrichedUser, ListUsersOptions } from '@fluxbase/sdk'
|
|
4
|
+
|
|
5
|
+
export interface UseUsersOptions extends ListUsersOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Whether to automatically fetch users on mount
|
|
8
|
+
* @default true
|
|
9
|
+
*/
|
|
10
|
+
autoFetch?: boolean
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Refetch interval in milliseconds (0 to disable)
|
|
14
|
+
* @default 0
|
|
15
|
+
*/
|
|
16
|
+
refetchInterval?: number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface UseUsersReturn {
|
|
20
|
+
/**
|
|
21
|
+
* Array of users
|
|
22
|
+
*/
|
|
23
|
+
users: EnrichedUser[]
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Total number of users (for pagination)
|
|
27
|
+
*/
|
|
28
|
+
total: number
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Whether users are being fetched
|
|
32
|
+
*/
|
|
33
|
+
isLoading: boolean
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Any error that occurred
|
|
37
|
+
*/
|
|
38
|
+
error: Error | null
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Refetch users
|
|
42
|
+
*/
|
|
43
|
+
refetch: () => Promise<void>
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Invite a new user
|
|
47
|
+
*/
|
|
48
|
+
inviteUser: (email: string, role: 'user' | 'admin') => Promise<void>
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Update user role
|
|
52
|
+
*/
|
|
53
|
+
updateUserRole: (userId: string, role: 'user' | 'admin') => Promise<void>
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Delete a user
|
|
57
|
+
*/
|
|
58
|
+
deleteUser: (userId: string) => Promise<void>
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Reset user password
|
|
62
|
+
*/
|
|
63
|
+
resetPassword: (userId: string) => Promise<{ message: string }>
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Hook for managing users
|
|
68
|
+
*
|
|
69
|
+
* Provides user list with pagination, search, and management functions.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```tsx
|
|
73
|
+
* function UserList() {
|
|
74
|
+
* const { users, total, isLoading, refetch, inviteUser, deleteUser } = useUsers({
|
|
75
|
+
* limit: 20,
|
|
76
|
+
* search: searchTerm
|
|
77
|
+
* })
|
|
78
|
+
*
|
|
79
|
+
* return (
|
|
80
|
+
* <div>
|
|
81
|
+
* {isLoading ? <Spinner /> : (
|
|
82
|
+
* <ul>
|
|
83
|
+
* {users.map(user => (
|
|
84
|
+
* <li key={user.id}>
|
|
85
|
+
* {user.email} - {user.role}
|
|
86
|
+
* <button onClick={() => deleteUser(user.id)}>Delete</button>
|
|
87
|
+
* </li>
|
|
88
|
+
* ))}
|
|
89
|
+
* </ul>
|
|
90
|
+
* )}
|
|
91
|
+
* </div>
|
|
92
|
+
* )
|
|
93
|
+
* }
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export function useUsers(options: UseUsersOptions = {}): UseUsersReturn {
|
|
97
|
+
const { autoFetch = true, refetchInterval = 0, ...listOptions } = options
|
|
98
|
+
const client = useFluxbaseClient()
|
|
99
|
+
|
|
100
|
+
const [users, setUsers] = useState<EnrichedUser[]>([])
|
|
101
|
+
const [total, setTotal] = useState(0)
|
|
102
|
+
const [isLoading, setIsLoading] = useState(autoFetch)
|
|
103
|
+
const [error, setError] = useState<Error | null>(null)
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Fetch users from API
|
|
107
|
+
*/
|
|
108
|
+
const fetchUsers = useCallback(async () => {
|
|
109
|
+
try {
|
|
110
|
+
setIsLoading(true)
|
|
111
|
+
setError(null)
|
|
112
|
+
const { data, error: apiError } = await client.admin.listUsers(listOptions)
|
|
113
|
+
if (apiError) {
|
|
114
|
+
throw apiError
|
|
115
|
+
}
|
|
116
|
+
setUsers(data!.users)
|
|
117
|
+
setTotal(data!.total)
|
|
118
|
+
} catch (err) {
|
|
119
|
+
setError(err as Error)
|
|
120
|
+
} finally {
|
|
121
|
+
setIsLoading(false)
|
|
122
|
+
}
|
|
123
|
+
}, [client, JSON.stringify(listOptions)])
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Invite a new user
|
|
127
|
+
*/
|
|
128
|
+
const inviteUser = useCallback(
|
|
129
|
+
async (email: string, role: 'user' | 'admin'): Promise<void> => {
|
|
130
|
+
await client.admin.inviteUser({ email, role })
|
|
131
|
+
await fetchUsers() // Refresh list
|
|
132
|
+
},
|
|
133
|
+
[client, fetchUsers]
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Update user role
|
|
138
|
+
*/
|
|
139
|
+
const updateUserRole = useCallback(
|
|
140
|
+
async (userId: string, role: 'user' | 'admin'): Promise<void> => {
|
|
141
|
+
await client.admin.updateUserRole(userId, role)
|
|
142
|
+
await fetchUsers() // Refresh list
|
|
143
|
+
},
|
|
144
|
+
[client, fetchUsers]
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Delete a user
|
|
149
|
+
*/
|
|
150
|
+
const deleteUser = useCallback(
|
|
151
|
+
async (userId: string): Promise<void> => {
|
|
152
|
+
await client.admin.deleteUser(userId)
|
|
153
|
+
await fetchUsers() // Refresh list
|
|
154
|
+
},
|
|
155
|
+
[client, fetchUsers]
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Reset user password
|
|
160
|
+
*/
|
|
161
|
+
const resetPassword = useCallback(
|
|
162
|
+
async (userId: string): Promise<{ message: string }> => {
|
|
163
|
+
const { data, error } = await client.admin.resetUserPassword(userId)
|
|
164
|
+
if (error) {
|
|
165
|
+
throw error
|
|
166
|
+
}
|
|
167
|
+
return data!
|
|
168
|
+
},
|
|
169
|
+
[client]
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
// Auto-fetch on mount
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
if (autoFetch) {
|
|
175
|
+
fetchUsers()
|
|
176
|
+
}
|
|
177
|
+
}, [autoFetch, fetchUsers])
|
|
178
|
+
|
|
179
|
+
// Set up refetch interval
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
if (refetchInterval > 0) {
|
|
182
|
+
const interval = setInterval(fetchUsers, refetchInterval)
|
|
183
|
+
return () => clearInterval(interval)
|
|
184
|
+
}
|
|
185
|
+
}, [refetchInterval, fetchUsers])
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
users,
|
|
189
|
+
total,
|
|
190
|
+
isLoading,
|
|
191
|
+
error,
|
|
192
|
+
refetch: fetchUsers,
|
|
193
|
+
inviteUser,
|
|
194
|
+
updateUserRole,
|
|
195
|
+
deleteUser,
|
|
196
|
+
resetPassword
|
|
197
|
+
}
|
|
198
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"jsx": "react-jsx",
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"declarationMap": true,
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
"outDir": "./dist",
|
|
11
|
+
"rootDir": "./src",
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"esModuleInterop": true,
|
|
17
|
+
"forceConsistentCasingInFileNames": true,
|
|
18
|
+
"strict": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"noEmit": true,
|
|
21
|
+
"baseUrl": ".",
|
|
22
|
+
"paths": {
|
|
23
|
+
"@fluxbase/sdk": ["../sdk/dist/index.d.ts"]
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"include": ["src/**/*"],
|
|
27
|
+
"exclude": ["node_modules", "dist"]
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["./src/context.tsx","./src/index.ts","./src/use-admin-auth.ts","./src/use-admin-hooks.ts","./src/use-client-keys.ts","./src/use-auth.ts","./src/use-query.ts","./src/use-realtime.ts","./src/use-rpc.ts","./src/use-storage.ts","./src/use-users.ts"],"version":"5.9.3"}
|
package/tsup.config.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { defineConfig } from 'tsup'
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
entry: ['src/index.ts'],
|
|
5
|
+
format: ['esm', 'cjs'],
|
|
6
|
+
dts: true,
|
|
7
|
+
splitting: false,
|
|
8
|
+
sourcemap: true,
|
|
9
|
+
clean: true,
|
|
10
|
+
external: ['react', '@tanstack/react-query', '@fluxbase/sdk'],
|
|
11
|
+
})
|
package/typedoc.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://typedoc.org/schema.json",
|
|
3
|
+
"entryPoints": ["src/index.ts"],
|
|
4
|
+
"out": "../docs/static/api/sdk-react",
|
|
5
|
+
"name": "@nimbleflux/fluxbase-sdk-react",
|
|
6
|
+
"readme": "README.md",
|
|
7
|
+
"plugin": [],
|
|
8
|
+
"excludePrivate": true,
|
|
9
|
+
"excludeProtected": false,
|
|
10
|
+
"excludeInternal": true,
|
|
11
|
+
"includeVersion": true,
|
|
12
|
+
"searchInComments": true,
|
|
13
|
+
"validation": {
|
|
14
|
+
"notExported": true,
|
|
15
|
+
"invalidLink": true,
|
|
16
|
+
"notDocumented": false
|
|
17
|
+
},
|
|
18
|
+
"categorizeByGroup": true,
|
|
19
|
+
"categoryOrder": [
|
|
20
|
+
"Context",
|
|
21
|
+
"Authentication Hooks",
|
|
22
|
+
"Database Hooks",
|
|
23
|
+
"Realtime Hooks",
|
|
24
|
+
"Storage Hooks",
|
|
25
|
+
"RPC Hooks",
|
|
26
|
+
"Types",
|
|
27
|
+
"*"
|
|
28
|
+
],
|
|
29
|
+
"navigationLinks": {
|
|
30
|
+
"GitHub": "https://github.com/nimbleflux/fluxbase",
|
|
31
|
+
"Documentation": "https://fluxbase.eu"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/vitest.config.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
test: {
|
|
5
|
+
environment: 'jsdom',
|
|
6
|
+
globals: true,
|
|
7
|
+
setupFiles: ['./src/test-setup.ts'],
|
|
8
|
+
coverage: {
|
|
9
|
+
provider: 'v8',
|
|
10
|
+
reporter: ['text', 'json', 'html', 'lcov'],
|
|
11
|
+
reportsDirectory: './coverage',
|
|
12
|
+
include: ['src/**/*.ts', 'src/**/*.tsx'],
|
|
13
|
+
exclude: ['src/**/*.test.ts', 'src/**/*.test.tsx', 'src/**/*.d.ts', 'src/test-setup.ts'],
|
|
14
|
+
thresholds: {
|
|
15
|
+
statements: 80,
|
|
16
|
+
branches: 80,
|
|
17
|
+
functions: 60,
|
|
18
|
+
lines: 80
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|