@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
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nimbleflux/fluxbase-sdk-react",
|
|
3
|
+
"version": "2026.3.6-rc.1",
|
|
4
|
+
"description": "React hooks for Fluxbase SDK",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsup",
|
|
17
|
+
"dev": "tsup --watch",
|
|
18
|
+
"docs": "typedoc",
|
|
19
|
+
"docs:watch": "typedoc --watch",
|
|
20
|
+
"type-check": "tsc --noEmit",
|
|
21
|
+
"format": "prettier --write src",
|
|
22
|
+
"format:check": "prettier --check src",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest",
|
|
25
|
+
"test:coverage": "vitest run --coverage"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"fluxbase",
|
|
29
|
+
"react",
|
|
30
|
+
"hooks",
|
|
31
|
+
"database",
|
|
32
|
+
"realtime"
|
|
33
|
+
],
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/nimbleflux/fluxbase"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"@nimbleflux/fluxbase-sdk": "^2026.3.5",
|
|
43
|
+
"@tanstack/react-query": "^5.90.21",
|
|
44
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
45
|
+
"@fluxbase/sdk": "^2026.3.6-rc.1"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@nimbleflux/fluxbase-sdk": "workspace:*",
|
|
49
|
+
"@tanstack/react-query": "^5.90.21",
|
|
50
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
51
|
+
"@testing-library/react": "^16.3.2",
|
|
52
|
+
"@types/react": "^19.2.14",
|
|
53
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
54
|
+
"jsdom": "^28.1.0",
|
|
55
|
+
"prettier": "^3.8.1",
|
|
56
|
+
"react": "^19.2.4",
|
|
57
|
+
"react-dom": "^19.2.4",
|
|
58
|
+
"tsup": "^8.5.1",
|
|
59
|
+
"typedoc": "^0.28.17",
|
|
60
|
+
"typescript": "^5.9.3",
|
|
61
|
+
"vitest": "^4.0.18"
|
|
62
|
+
},
|
|
63
|
+
"engines": {
|
|
64
|
+
"node": ">=24.14.0"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for FluxbaseProvider and useFluxbaseClient
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
6
|
+
import { render, screen, renderHook } from '@testing-library/react';
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { FluxbaseProvider, useFluxbaseClient } from './context';
|
|
9
|
+
import { createMockClient } from './test-utils';
|
|
10
|
+
import type { FluxbaseClient } from '@nimbleflux/fluxbase-sdk';
|
|
11
|
+
|
|
12
|
+
describe('FluxbaseProvider', () => {
|
|
13
|
+
it('should render children', () => {
|
|
14
|
+
const client = createMockClient();
|
|
15
|
+
render(
|
|
16
|
+
<FluxbaseProvider client={client}>
|
|
17
|
+
<div data-testid="child">Hello</div>
|
|
18
|
+
</FluxbaseProvider>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
expect(screen.getByTestId('child')).toHaveTextContent('Hello');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should provide client to children', () => {
|
|
25
|
+
const client = createMockClient();
|
|
26
|
+
let receivedClient: FluxbaseClient | null = null;
|
|
27
|
+
|
|
28
|
+
function TestComponent() {
|
|
29
|
+
receivedClient = useFluxbaseClient();
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
render(
|
|
34
|
+
<FluxbaseProvider client={client}>
|
|
35
|
+
<TestComponent />
|
|
36
|
+
</FluxbaseProvider>
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
expect(receivedClient).toBe(client);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should support nested children', () => {
|
|
43
|
+
const client = createMockClient();
|
|
44
|
+
render(
|
|
45
|
+
<FluxbaseProvider client={client}>
|
|
46
|
+
<div>
|
|
47
|
+
<span>
|
|
48
|
+
<p data-testid="nested">Nested content</p>
|
|
49
|
+
</span>
|
|
50
|
+
</div>
|
|
51
|
+
</FluxbaseProvider>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(screen.getByTestId('nested')).toHaveTextContent('Nested content');
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('useFluxbaseClient', () => {
|
|
59
|
+
it('should return the client from context', () => {
|
|
60
|
+
const client = createMockClient();
|
|
61
|
+
|
|
62
|
+
const { result } = renderHook(() => useFluxbaseClient(), {
|
|
63
|
+
wrapper: ({ children }) => (
|
|
64
|
+
<FluxbaseProvider client={client}>{children}</FluxbaseProvider>
|
|
65
|
+
),
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
expect(result.current).toBe(client);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should throw error when used outside provider', () => {
|
|
72
|
+
// Suppress console.error for this test
|
|
73
|
+
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
74
|
+
|
|
75
|
+
expect(() => {
|
|
76
|
+
renderHook(() => useFluxbaseClient());
|
|
77
|
+
}).toThrow('useFluxbaseClient must be used within a FluxbaseProvider');
|
|
78
|
+
|
|
79
|
+
consoleSpy.mockRestore();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should provide access to auth methods', () => {
|
|
83
|
+
const client = createMockClient();
|
|
84
|
+
|
|
85
|
+
const { result } = renderHook(() => useFluxbaseClient(), {
|
|
86
|
+
wrapper: ({ children }) => (
|
|
87
|
+
<FluxbaseProvider client={client}>{children}</FluxbaseProvider>
|
|
88
|
+
),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
expect(result.current.auth).toBeDefined();
|
|
92
|
+
expect(result.current.auth.getSession).toBeDefined();
|
|
93
|
+
expect(result.current.auth.signIn).toBeDefined();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should provide access to storage methods', () => {
|
|
97
|
+
const client = createMockClient();
|
|
98
|
+
|
|
99
|
+
const { result } = renderHook(() => useFluxbaseClient(), {
|
|
100
|
+
wrapper: ({ children }) => (
|
|
101
|
+
<FluxbaseProvider client={client}>{children}</FluxbaseProvider>
|
|
102
|
+
),
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
expect(result.current.storage).toBeDefined();
|
|
106
|
+
expect(result.current.storage.from).toBeDefined();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should provide access to realtime methods', () => {
|
|
110
|
+
const client = createMockClient();
|
|
111
|
+
|
|
112
|
+
const { result } = renderHook(() => useFluxbaseClient(), {
|
|
113
|
+
wrapper: ({ children }) => (
|
|
114
|
+
<FluxbaseProvider client={client}>{children}</FluxbaseProvider>
|
|
115
|
+
),
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
expect(result.current.realtime).toBeDefined();
|
|
119
|
+
expect(result.current.realtime.channel).toBeDefined();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should provide access to graphql methods', () => {
|
|
123
|
+
const client = createMockClient();
|
|
124
|
+
|
|
125
|
+
const { result } = renderHook(() => useFluxbaseClient(), {
|
|
126
|
+
wrapper: ({ children }) => (
|
|
127
|
+
<FluxbaseProvider client={client}>{children}</FluxbaseProvider>
|
|
128
|
+
),
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
expect(result.current.graphql).toBeDefined();
|
|
132
|
+
expect(result.current.graphql.execute).toBeDefined();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should provide access to admin methods', () => {
|
|
136
|
+
const client = createMockClient();
|
|
137
|
+
|
|
138
|
+
const { result } = renderHook(() => useFluxbaseClient(), {
|
|
139
|
+
wrapper: ({ children }) => (
|
|
140
|
+
<FluxbaseProvider client={client}>{children}</FluxbaseProvider>
|
|
141
|
+
),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
expect(result.current.admin).toBeDefined();
|
|
145
|
+
expect(result.current.admin.me).toBeDefined();
|
|
146
|
+
});
|
|
147
|
+
});
|
package/src/context.tsx
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React context for Fluxbase client
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createContext, useContext, type ReactNode } from 'react'
|
|
6
|
+
import type { FluxbaseClient } from '@nimbleflux/fluxbase-sdk'
|
|
7
|
+
|
|
8
|
+
const FluxbaseContext = createContext<FluxbaseClient | null>(null)
|
|
9
|
+
|
|
10
|
+
export interface FluxbaseProviderProps {
|
|
11
|
+
client: FluxbaseClient
|
|
12
|
+
children: ReactNode
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Provider component to make Fluxbase client available throughout the app
|
|
17
|
+
*/
|
|
18
|
+
export function FluxbaseProvider({ client, children }: FluxbaseProviderProps) {
|
|
19
|
+
return <FluxbaseContext.Provider value={client}>{children}</FluxbaseContext.Provider>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Hook to access the Fluxbase client from context
|
|
24
|
+
*/
|
|
25
|
+
export function useFluxbaseClient(): FluxbaseClient {
|
|
26
|
+
const client = useContext(FluxbaseContext)
|
|
27
|
+
|
|
28
|
+
if (!client) {
|
|
29
|
+
throw new Error('useFluxbaseClient must be used within a FluxbaseProvider')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return client
|
|
33
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for module exports
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect } from 'vitest';
|
|
6
|
+
import * as exports from './index';
|
|
7
|
+
|
|
8
|
+
describe('Module Exports', () => {
|
|
9
|
+
describe('Context exports', () => {
|
|
10
|
+
it('should export FluxbaseProvider', () => {
|
|
11
|
+
expect(exports.FluxbaseProvider).toBeDefined();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should export useFluxbaseClient', () => {
|
|
15
|
+
expect(exports.useFluxbaseClient).toBeDefined();
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('Auth hook exports', () => {
|
|
20
|
+
it('should export useAuth', () => {
|
|
21
|
+
expect(exports.useAuth).toBeDefined();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should export useUser', () => {
|
|
25
|
+
expect(exports.useUser).toBeDefined();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should export useSession', () => {
|
|
29
|
+
expect(exports.useSession).toBeDefined();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should export useSignIn', () => {
|
|
33
|
+
expect(exports.useSignIn).toBeDefined();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should export useSignUp', () => {
|
|
37
|
+
expect(exports.useSignUp).toBeDefined();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should export useSignOut', () => {
|
|
41
|
+
expect(exports.useSignOut).toBeDefined();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should export useUpdateUser', () => {
|
|
45
|
+
expect(exports.useUpdateUser).toBeDefined();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('CAPTCHA hook exports', () => {
|
|
50
|
+
it('should export useCaptchaConfig', () => {
|
|
51
|
+
expect(exports.useCaptchaConfig).toBeDefined();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should export useCaptcha', () => {
|
|
55
|
+
expect(exports.useCaptcha).toBeDefined();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should export isCaptchaRequiredForEndpoint', () => {
|
|
59
|
+
expect(exports.isCaptchaRequiredForEndpoint).toBeDefined();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('Auth config exports', () => {
|
|
64
|
+
it('should export useAuthConfig', () => {
|
|
65
|
+
expect(exports.useAuthConfig).toBeDefined();
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('SAML hook exports', () => {
|
|
70
|
+
it('should export useSAMLProviders', () => {
|
|
71
|
+
expect(exports.useSAMLProviders).toBeDefined();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should export useGetSAMLLoginUrl', () => {
|
|
75
|
+
expect(exports.useGetSAMLLoginUrl).toBeDefined();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should export useSignInWithSAML', () => {
|
|
79
|
+
expect(exports.useSignInWithSAML).toBeDefined();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should export useHandleSAMLCallback', () => {
|
|
83
|
+
expect(exports.useHandleSAMLCallback).toBeDefined();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should export useSAMLMetadataUrl', () => {
|
|
87
|
+
expect(exports.useSAMLMetadataUrl).toBeDefined();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('GraphQL hook exports', () => {
|
|
92
|
+
it('should export useGraphQLQuery', () => {
|
|
93
|
+
expect(exports.useGraphQLQuery).toBeDefined();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should export useGraphQLMutation', () => {
|
|
97
|
+
expect(exports.useGraphQLMutation).toBeDefined();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should export useGraphQLIntrospection', () => {
|
|
101
|
+
expect(exports.useGraphQLIntrospection).toBeDefined();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should export useGraphQL', () => {
|
|
105
|
+
expect(exports.useGraphQL).toBeDefined();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('Database query hook exports', () => {
|
|
110
|
+
it('should export useFluxbaseQuery', () => {
|
|
111
|
+
expect(exports.useFluxbaseQuery).toBeDefined();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should export useTable', () => {
|
|
115
|
+
expect(exports.useTable).toBeDefined();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('should export useInsert', () => {
|
|
119
|
+
expect(exports.useInsert).toBeDefined();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should export useUpdate', () => {
|
|
123
|
+
expect(exports.useUpdate).toBeDefined();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should export useUpsert', () => {
|
|
127
|
+
expect(exports.useUpsert).toBeDefined();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should export useDelete', () => {
|
|
131
|
+
expect(exports.useDelete).toBeDefined();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe('Realtime hook exports', () => {
|
|
136
|
+
it('should export useRealtime', () => {
|
|
137
|
+
expect(exports.useRealtime).toBeDefined();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should export useTableSubscription', () => {
|
|
141
|
+
expect(exports.useTableSubscription).toBeDefined();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should export useTableInserts', () => {
|
|
145
|
+
expect(exports.useTableInserts).toBeDefined();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should export useTableUpdates', () => {
|
|
149
|
+
expect(exports.useTableUpdates).toBeDefined();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should export useTableDeletes', () => {
|
|
153
|
+
expect(exports.useTableDeletes).toBeDefined();
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe('Storage hook exports', () => {
|
|
158
|
+
it('should export useStorageList', () => {
|
|
159
|
+
expect(exports.useStorageList).toBeDefined();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('should export useStorageUpload', () => {
|
|
163
|
+
expect(exports.useStorageUpload).toBeDefined();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('should export useStorageUploadWithProgress', () => {
|
|
167
|
+
expect(exports.useStorageUploadWithProgress).toBeDefined();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('should export useStorageDownload', () => {
|
|
171
|
+
expect(exports.useStorageDownload).toBeDefined();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should export useStorageDelete', () => {
|
|
175
|
+
expect(exports.useStorageDelete).toBeDefined();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('should export useStoragePublicUrl', () => {
|
|
179
|
+
expect(exports.useStoragePublicUrl).toBeDefined();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('should export useStorageTransformUrl', () => {
|
|
183
|
+
expect(exports.useStorageTransformUrl).toBeDefined();
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('should export useStorageSignedUrl', () => {
|
|
187
|
+
expect(exports.useStorageSignedUrl).toBeDefined();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('should export useStorageSignedUrlWithOptions', () => {
|
|
191
|
+
expect(exports.useStorageSignedUrlWithOptions).toBeDefined();
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('should export useStorageMove', () => {
|
|
195
|
+
expect(exports.useStorageMove).toBeDefined();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('should export useStorageCopy', () => {
|
|
199
|
+
expect(exports.useStorageCopy).toBeDefined();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('should export useStorageBuckets', () => {
|
|
203
|
+
expect(exports.useStorageBuckets).toBeDefined();
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('should export useCreateBucket', () => {
|
|
207
|
+
expect(exports.useCreateBucket).toBeDefined();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('should export useDeleteBucket', () => {
|
|
211
|
+
expect(exports.useDeleteBucket).toBeDefined();
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
describe('Admin hook exports', () => {
|
|
216
|
+
it('should export useAdminAuth', () => {
|
|
217
|
+
expect(exports.useAdminAuth).toBeDefined();
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should export useUsers', () => {
|
|
221
|
+
expect(exports.useUsers).toBeDefined();
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('should export useClientKeys', () => {
|
|
225
|
+
expect(exports.useClientKeys).toBeDefined();
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('should export useAPIKeys (deprecated alias)', () => {
|
|
229
|
+
expect(exports.useAPIKeys).toBeDefined();
|
|
230
|
+
expect(exports.useAPIKeys).toBe(exports.useClientKeys);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('should export useWebhooks', () => {
|
|
234
|
+
expect(exports.useWebhooks).toBeDefined();
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('should export useAppSettings', () => {
|
|
238
|
+
expect(exports.useAppSettings).toBeDefined();
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('should export useSystemSettings', () => {
|
|
242
|
+
expect(exports.useSystemSettings).toBeDefined();
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
describe('Total export count', () => {
|
|
247
|
+
it('should export the expected number of items', () => {
|
|
248
|
+
// Count the exports (functions and types are counted)
|
|
249
|
+
const exportKeys = Object.keys(exports);
|
|
250
|
+
|
|
251
|
+
// We expect at least 50 exports (hooks, types, etc.)
|
|
252
|
+
expect(exportKeys.length).toBeGreaterThanOrEqual(50);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fluxbase React Hooks
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```tsx
|
|
6
|
+
* import { createClient } from '@nimbleflux/fluxbase-sdk'
|
|
7
|
+
* import { FluxbaseProvider, useAuth, useTable } from '@nimbleflux/fluxbase-sdk-react'
|
|
8
|
+
* import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
9
|
+
*
|
|
10
|
+
* const client = createClient({ url: 'http://localhost:8080' })
|
|
11
|
+
* const queryClient = new QueryClient()
|
|
12
|
+
*
|
|
13
|
+
* function App() {
|
|
14
|
+
* return (
|
|
15
|
+
* <QueryClientProvider client={queryClient}>
|
|
16
|
+
* <FluxbaseProvider client={client}>
|
|
17
|
+
* <MyComponent />
|
|
18
|
+
* </FluxbaseProvider>
|
|
19
|
+
* </QueryClientProvider>
|
|
20
|
+
* )
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* function MyComponent() {
|
|
24
|
+
* const { user, signIn, signOut } = useAuth()
|
|
25
|
+
* const { data: products } = useTable('products', (q) => q.select('*').eq('active', true))
|
|
26
|
+
*
|
|
27
|
+
* return <div>...</div>
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
// Context and provider
|
|
33
|
+
export { FluxbaseProvider, useFluxbaseClient } from "./context";
|
|
34
|
+
|
|
35
|
+
// Auth hooks
|
|
36
|
+
export {
|
|
37
|
+
useAuth,
|
|
38
|
+
useUser,
|
|
39
|
+
useSession,
|
|
40
|
+
useSignIn,
|
|
41
|
+
useSignUp,
|
|
42
|
+
useSignOut,
|
|
43
|
+
useUpdateUser,
|
|
44
|
+
} from "./use-auth";
|
|
45
|
+
|
|
46
|
+
// CAPTCHA hooks
|
|
47
|
+
export {
|
|
48
|
+
useCaptchaConfig,
|
|
49
|
+
useCaptcha,
|
|
50
|
+
isCaptchaRequiredForEndpoint,
|
|
51
|
+
type CaptchaState,
|
|
52
|
+
} from "./use-captcha";
|
|
53
|
+
|
|
54
|
+
// Auth configuration hooks
|
|
55
|
+
export { useAuthConfig } from "./use-auth-config";
|
|
56
|
+
|
|
57
|
+
// SAML SSO hooks
|
|
58
|
+
export {
|
|
59
|
+
useSAMLProviders,
|
|
60
|
+
useGetSAMLLoginUrl,
|
|
61
|
+
useSignInWithSAML,
|
|
62
|
+
useHandleSAMLCallback,
|
|
63
|
+
useSAMLMetadataUrl,
|
|
64
|
+
} from "./use-saml";
|
|
65
|
+
|
|
66
|
+
// GraphQL hooks
|
|
67
|
+
export {
|
|
68
|
+
useGraphQLQuery,
|
|
69
|
+
useGraphQLMutation,
|
|
70
|
+
useGraphQLIntrospection,
|
|
71
|
+
useGraphQL,
|
|
72
|
+
type UseGraphQLQueryOptions,
|
|
73
|
+
type UseGraphQLMutationOptions,
|
|
74
|
+
} from "./use-graphql";
|
|
75
|
+
|
|
76
|
+
// Database query hooks
|
|
77
|
+
export {
|
|
78
|
+
useFluxbaseQuery,
|
|
79
|
+
useTable,
|
|
80
|
+
useInsert,
|
|
81
|
+
useUpdate,
|
|
82
|
+
useUpsert,
|
|
83
|
+
useDelete,
|
|
84
|
+
} from "./use-query";
|
|
85
|
+
|
|
86
|
+
// Realtime hooks
|
|
87
|
+
export {
|
|
88
|
+
useRealtime,
|
|
89
|
+
useTableSubscription,
|
|
90
|
+
useTableInserts,
|
|
91
|
+
useTableUpdates,
|
|
92
|
+
useTableDeletes,
|
|
93
|
+
} from "./use-realtime";
|
|
94
|
+
|
|
95
|
+
// Storage hooks
|
|
96
|
+
export {
|
|
97
|
+
useStorageList,
|
|
98
|
+
useStorageUpload,
|
|
99
|
+
useStorageUploadWithProgress,
|
|
100
|
+
useStorageDownload,
|
|
101
|
+
useStorageDelete,
|
|
102
|
+
useStoragePublicUrl,
|
|
103
|
+
useStorageTransformUrl,
|
|
104
|
+
useStorageSignedUrl,
|
|
105
|
+
useStorageSignedUrlWithOptions,
|
|
106
|
+
useStorageMove,
|
|
107
|
+
useStorageCopy,
|
|
108
|
+
useStorageBuckets,
|
|
109
|
+
useCreateBucket,
|
|
110
|
+
useDeleteBucket,
|
|
111
|
+
} from "./use-storage";
|
|
112
|
+
|
|
113
|
+
// Admin hooks
|
|
114
|
+
export { useAdminAuth } from "./use-admin-auth";
|
|
115
|
+
export { useUsers } from "./use-users";
|
|
116
|
+
export { useClientKeys, useAPIKeys } from "./use-client-keys";
|
|
117
|
+
export {
|
|
118
|
+
useWebhooks,
|
|
119
|
+
useAppSettings,
|
|
120
|
+
useSystemSettings,
|
|
121
|
+
} from "./use-admin-hooks";
|
|
122
|
+
|
|
123
|
+
// Table export hooks
|
|
124
|
+
export {
|
|
125
|
+
useTableDetails,
|
|
126
|
+
useExportTable,
|
|
127
|
+
useTableExportSyncs,
|
|
128
|
+
useCreateTableExportSync,
|
|
129
|
+
useUpdateTableExportSync,
|
|
130
|
+
useDeleteTableExportSync,
|
|
131
|
+
useTriggerTableExportSync,
|
|
132
|
+
type UseTableDetailsOptions,
|
|
133
|
+
type UseTableDetailsReturn,
|
|
134
|
+
type UseExportTableReturn,
|
|
135
|
+
type UseTableExportSyncsOptions,
|
|
136
|
+
type UseTableExportSyncsReturn,
|
|
137
|
+
type UseCreateTableExportSyncReturn,
|
|
138
|
+
type UseUpdateTableExportSyncReturn,
|
|
139
|
+
type UseDeleteTableExportSyncReturn,
|
|
140
|
+
type UseTriggerTableExportSyncReturn,
|
|
141
|
+
} from "./use-table-export";
|
|
142
|
+
|
|
143
|
+
// Re-export types from SDK
|
|
144
|
+
export type {
|
|
145
|
+
FluxbaseClient,
|
|
146
|
+
AuthSession,
|
|
147
|
+
User,
|
|
148
|
+
SignInCredentials,
|
|
149
|
+
SignUpCredentials,
|
|
150
|
+
PostgrestResponse,
|
|
151
|
+
RealtimeChangePayload,
|
|
152
|
+
StorageObject,
|
|
153
|
+
AdminUser,
|
|
154
|
+
EnrichedUser,
|
|
155
|
+
ClientKey,
|
|
156
|
+
APIKey, // Deprecated alias
|
|
157
|
+
Webhook,
|
|
158
|
+
AppSettings,
|
|
159
|
+
SystemSetting,
|
|
160
|
+
CaptchaConfig,
|
|
161
|
+
CaptchaProvider,
|
|
162
|
+
TransformOptions,
|
|
163
|
+
ImageFitMode,
|
|
164
|
+
ImageFormat,
|
|
165
|
+
SignedUrlOptions,
|
|
166
|
+
SAMLProvider,
|
|
167
|
+
SAMLProvidersResponse,
|
|
168
|
+
SAMLLoginOptions,
|
|
169
|
+
SAMLLoginResponse,
|
|
170
|
+
SAMLSession,
|
|
171
|
+
GraphQLResponse,
|
|
172
|
+
GraphQLError,
|
|
173
|
+
GraphQLErrorLocation,
|
|
174
|
+
GraphQLRequestOptions,
|
|
175
|
+
} from "@nimbleflux/fluxbase-sdk";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test setup file for Fluxbase React SDK
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { vi } from 'vitest';
|
|
6
|
+
import '@testing-library/react';
|
|
7
|
+
import '@testing-library/jest-dom/vitest';
|
|
8
|
+
|
|
9
|
+
// Mock window.location for tests that need it
|
|
10
|
+
Object.defineProperty(window, 'location', {
|
|
11
|
+
value: {
|
|
12
|
+
href: 'http://localhost:3000',
|
|
13
|
+
origin: 'http://localhost:3000',
|
|
14
|
+
pathname: '/',
|
|
15
|
+
search: '',
|
|
16
|
+
hash: '',
|
|
17
|
+
assign: vi.fn(),
|
|
18
|
+
replace: vi.fn(),
|
|
19
|
+
reload: vi.fn(),
|
|
20
|
+
},
|
|
21
|
+
writable: true,
|
|
22
|
+
});
|