@zveltio/react 1.2.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 +130 -0
- package/dist/context.d.ts +9 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +13 -0
- package/dist/hooks/useAuth.d.ts +9 -0
- package/dist/hooks/useAuth.d.ts.map +1 -0
- package/dist/hooks/useAuth.js +61 -0
- package/dist/hooks/useCollection.d.ts +6 -0
- package/dist/hooks/useCollection.d.ts.map +1 -0
- package/dist/hooks/useCollection.js +24 -0
- package/dist/hooks/useRealtime.d.ts +2 -0
- package/dist/hooks/useRealtime.d.ts.map +1 -0
- package/dist/hooks/useRealtime.js +24 -0
- package/dist/hooks/useRecord.d.ts +5 -0
- package/dist/hooks/useRecord.d.ts.map +1 -0
- package/dist/hooks/useRecord.js +29 -0
- package/dist/hooks/useStorage.d.ts +9 -0
- package/dist/hooks/useStorage.d.ts.map +1 -0
- package/dist/hooks/useStorage.js +26 -0
- package/dist/hooks/useSyncCollection.d.ts +7 -0
- package/dist/hooks/useSyncCollection.d.ts.map +1 -0
- package/dist/hooks/useSyncCollection.js +31 -0
- package/dist/hooks/useSyncStatus.d.ts +4 -0
- package/dist/hooks/useSyncStatus.d.ts.map +1 -0
- package/dist/hooks/useSyncStatus.js +47 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# @zveltio/react
|
|
2
|
+
|
|
3
|
+
Official React SDK for [Zveltio](https://zveltio.com) — hooks for collections, real-time, auth, storage, and offline sync.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @zveltio/react @zveltio/sdk
|
|
9
|
+
# or
|
|
10
|
+
bun add @zveltio/react @zveltio/sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
Wrap your app with `ZveltioProvider`:
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { ZveltioProvider } from '@zveltio/react';
|
|
19
|
+
|
|
20
|
+
export default function App() {
|
|
21
|
+
return (
|
|
22
|
+
<ZveltioProvider url="https://your-engine.example.com">
|
|
23
|
+
<YourApp />
|
|
24
|
+
</ZveltioProvider>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Hooks
|
|
30
|
+
|
|
31
|
+
### Data
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { useCollection, useRecord } from '@zveltio/react';
|
|
35
|
+
|
|
36
|
+
function ProductList() {
|
|
37
|
+
const { data, loading, error, refresh } = useCollection('products', {
|
|
38
|
+
filter: { status: 'active' },
|
|
39
|
+
sort: '-createdAt',
|
|
40
|
+
limit: 20,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (loading) return <Spinner />;
|
|
44
|
+
return data.map((p) => <ProductCard key={p.id} product={p} />);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function ProductDetail({ id }: { id: string }) {
|
|
48
|
+
const { data: product } = useRecord('products', id);
|
|
49
|
+
return <div>{product?.name}</div>;
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Real-time
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import { useRealtime } from '@zveltio/react';
|
|
57
|
+
|
|
58
|
+
function LiveFeed() {
|
|
59
|
+
const event = useRealtime('orders');
|
|
60
|
+
// event: { action: 'create'|'update'|'delete', record: {...} } | null
|
|
61
|
+
return <div>Last event: {event?.action}</div>;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Offline Sync
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { useSyncCollection, useSyncStatus } from '@zveltio/react';
|
|
69
|
+
|
|
70
|
+
function OfflineProducts() {
|
|
71
|
+
const { records, pending, conflicts } = useSyncCollection('products');
|
|
72
|
+
const { isOnline } = useSyncStatus();
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<>
|
|
76
|
+
{!isOnline && <Banner>Offline — syncing when reconnected</Banner>}
|
|
77
|
+
{records.map((p) => (
|
|
78
|
+
<div key={p.id} style={{ opacity: p._syncStatus === 'pending' ? 0.6 : 1 }}>
|
|
79
|
+
{p.name}
|
|
80
|
+
</div>
|
|
81
|
+
))}
|
|
82
|
+
</>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Auth
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
import { useAuth } from '@zveltio/react';
|
|
91
|
+
|
|
92
|
+
function Header() {
|
|
93
|
+
const { user, signIn, signOut, loading } = useAuth();
|
|
94
|
+
|
|
95
|
+
if (loading) return null;
|
|
96
|
+
if (!user) return <button onClick={() => signIn({ email, password })}>Sign In</button>;
|
|
97
|
+
return (
|
|
98
|
+
<div>
|
|
99
|
+
{user.email} <button onClick={signOut}>Sign Out</button>
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Storage
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
import { useStorage } from '@zveltio/react';
|
|
109
|
+
|
|
110
|
+
function FileUpload() {
|
|
111
|
+
const { upload, uploading, progress } = useStorage();
|
|
112
|
+
|
|
113
|
+
const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
114
|
+
const file = e.target.files?.[0];
|
|
115
|
+
if (file) {
|
|
116
|
+
const url = await upload(file);
|
|
117
|
+
console.log('Uploaded:', url);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
return <input type="file" onChange={handleFile} disabled={uploading} />;
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Links
|
|
126
|
+
|
|
127
|
+
- [Documentation](https://zveltio.com/docs)
|
|
128
|
+
- [GitHub](https://github.com/zveltio/zveltio)
|
|
129
|
+
- [Core SDK](https://www.npmjs.com/package/@zveltio/sdk)
|
|
130
|
+
- [Vue SDK](https://www.npmjs.com/package/@zveltio/vue)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ZveltioClient } from '@zveltio/sdk';
|
|
3
|
+
export interface ZveltioProviderProps {
|
|
4
|
+
client: ZveltioClient;
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
}
|
|
7
|
+
export declare function ZveltioProvider({ client, children }: ZveltioProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare function useZveltioClient(): ZveltioClient;
|
|
9
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,oBAAoB,2CAMzE;AAED,wBAAgB,gBAAgB,IAAI,aAAa,CAMhD"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
|
+
const ZveltioContext = createContext(null);
|
|
4
|
+
export function ZveltioProvider({ client, children }) {
|
|
5
|
+
return (_jsx(ZveltioContext.Provider, { value: client, children: children }));
|
|
6
|
+
}
|
|
7
|
+
export function useZveltioClient() {
|
|
8
|
+
const client = useContext(ZveltioContext);
|
|
9
|
+
if (!client) {
|
|
10
|
+
throw new Error('useZveltioClient must be used within a ZveltioProvider');
|
|
11
|
+
}
|
|
12
|
+
return client;
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type AuthState } from '@zveltio/sdk';
|
|
2
|
+
import type { HookResult } from '../types.js';
|
|
3
|
+
export type { AuthState };
|
|
4
|
+
export declare function useAuth(): HookResult<AuthState> & {
|
|
5
|
+
login: (email: string, password: string) => Promise<void>;
|
|
6
|
+
logout: () => Promise<void>;
|
|
7
|
+
signup: (email: string, password: string, name: string) => Promise<void>;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=useAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../../src/hooks/useAuth.ts"],"names":[],"mappings":"AACA,OAAO,EAAmD,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAE/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,wBAAgB,OAAO,IAAI,UAAU,CAAC,SAAS,CAAC,GAAG;IACjD,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1E,CAwDA"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { fetchSession, loginUser, logoutUser, signupUser } from '@zveltio/sdk';
|
|
3
|
+
import { useZveltioClient } from '../context.js';
|
|
4
|
+
export function useAuth() {
|
|
5
|
+
const client = useZveltioClient();
|
|
6
|
+
const [data, setData] = useState(null);
|
|
7
|
+
const [loading, setLoading] = useState(true);
|
|
8
|
+
const [error, setError] = useState(null);
|
|
9
|
+
const loadSession = useCallback(async () => {
|
|
10
|
+
try {
|
|
11
|
+
setData(await fetchSession(client));
|
|
12
|
+
}
|
|
13
|
+
finally {
|
|
14
|
+
setLoading(false);
|
|
15
|
+
}
|
|
16
|
+
}, [client]);
|
|
17
|
+
useEffect(() => { loadSession(); }, [loadSession]);
|
|
18
|
+
const login = useCallback(async (email, password) => {
|
|
19
|
+
setLoading(true);
|
|
20
|
+
setError(null);
|
|
21
|
+
try {
|
|
22
|
+
setData(await loginUser(client, email, password));
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
setLoading(false);
|
|
30
|
+
}
|
|
31
|
+
}, [client]);
|
|
32
|
+
const logout = useCallback(async () => {
|
|
33
|
+
setLoading(true);
|
|
34
|
+
setError(null);
|
|
35
|
+
try {
|
|
36
|
+
setData(await logoutUser(client));
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
setLoading(false);
|
|
44
|
+
}
|
|
45
|
+
}, [client]);
|
|
46
|
+
const signup = useCallback(async (email, password, name) => {
|
|
47
|
+
setLoading(true);
|
|
48
|
+
setError(null);
|
|
49
|
+
try {
|
|
50
|
+
setData(await signupUser(client, email, password, name));
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
setLoading(false);
|
|
58
|
+
}
|
|
59
|
+
}, [client]);
|
|
60
|
+
return { data, loading, error, login, logout, signup };
|
|
61
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type CollectionOptions } from '@zveltio/sdk';
|
|
2
|
+
import type { HookResult } from '../types.js';
|
|
3
|
+
export declare function useCollection<T = any>(collectionName: string, options?: CollectionOptions): HookResult<T[]> & {
|
|
4
|
+
refetch: () => void;
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=useCollection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCollection.d.ts","sourceRoot":"","sources":["../../src/hooks/useCollection.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,wBAAgB,aAAa,CAAC,CAAC,GAAG,GAAG,EACnC,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,UAAU,CAAC,CAAC,EAAE,CAAC,GAAG;IAAE,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAqB3C"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { fetchCollection } from '@zveltio/sdk';
|
|
3
|
+
import { useZveltioClient } from '../context.js';
|
|
4
|
+
export function useCollection(collectionName, options) {
|
|
5
|
+
const client = useZveltioClient();
|
|
6
|
+
const [data, setData] = useState(null);
|
|
7
|
+
const [loading, setLoading] = useState(true);
|
|
8
|
+
const [error, setError] = useState(null);
|
|
9
|
+
const load = useCallback(async () => {
|
|
10
|
+
setLoading(true);
|
|
11
|
+
setError(null);
|
|
12
|
+
try {
|
|
13
|
+
setData(await fetchCollection(client, collectionName, options));
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
17
|
+
}
|
|
18
|
+
finally {
|
|
19
|
+
setLoading(false);
|
|
20
|
+
}
|
|
21
|
+
}, [client, collectionName, JSON.stringify(options)]);
|
|
22
|
+
useEffect(() => { load(); }, [load]);
|
|
23
|
+
return { data, loading, error, refetch: load };
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRealtime.d.ts","sourceRoot":"","sources":["../../src/hooks/useRealtime.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,GAC5B,IAAI,CAwBN"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { ZveltioRealtime } from '@zveltio/sdk';
|
|
3
|
+
export function useRealtime(baseUrl, collection, event, callback) {
|
|
4
|
+
const realtimeRef = useRef(null);
|
|
5
|
+
const callbackRef = useRef(callback);
|
|
6
|
+
callbackRef.current = callback;
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
if (!baseUrl || !collection)
|
|
9
|
+
return;
|
|
10
|
+
const realtime = new ZveltioRealtime(baseUrl);
|
|
11
|
+
realtimeRef.current = realtime;
|
|
12
|
+
realtime.connect();
|
|
13
|
+
const unsub = realtime.subscribe(collection, (data) => {
|
|
14
|
+
if (!event || data.event === event) {
|
|
15
|
+
callbackRef.current(data);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
return () => {
|
|
19
|
+
unsub();
|
|
20
|
+
realtime.disconnect();
|
|
21
|
+
realtimeRef.current = null;
|
|
22
|
+
};
|
|
23
|
+
}, [baseUrl, collection, event]);
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRecord.d.ts","sourceRoot":"","sources":["../../src/hooks/useRecord.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,wBAAgB,SAAS,CAAC,CAAC,GAAG,GAAG,EAC/B,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC5B,UAAU,CAAC,CAAC,CAAC,GAAG;IAAE,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAsBzC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { fetchRecord } from '@zveltio/sdk';
|
|
3
|
+
import { useZveltioClient } from '../context.js';
|
|
4
|
+
export function useRecord(collectionName, id) {
|
|
5
|
+
const client = useZveltioClient();
|
|
6
|
+
const [data, setData] = useState(null);
|
|
7
|
+
const [loading, setLoading] = useState(!!id);
|
|
8
|
+
const [error, setError] = useState(null);
|
|
9
|
+
const load = useCallback(async () => {
|
|
10
|
+
if (!id) {
|
|
11
|
+
setData(null);
|
|
12
|
+
setLoading(false);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
setLoading(true);
|
|
16
|
+
setError(null);
|
|
17
|
+
try {
|
|
18
|
+
setData(await fetchRecord(client, collectionName, id));
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
setLoading(false);
|
|
25
|
+
}
|
|
26
|
+
}, [client, collectionName, id]);
|
|
27
|
+
useEffect(() => { load(); }, [load]);
|
|
28
|
+
return { data, loading, error, refetch: load };
|
|
29
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type StorageFile } from '@zveltio/sdk';
|
|
2
|
+
export declare function useStorage(): {
|
|
3
|
+
upload: (file: File, folder?: string) => Promise<StorageFile>;
|
|
4
|
+
list: (folder?: string) => Promise<StorageFile[]>;
|
|
5
|
+
remove: (fileId: string) => Promise<void>;
|
|
6
|
+
uploading: boolean;
|
|
7
|
+
error: Error | null;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=useStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStorage.d.ts","sourceRoot":"","sources":["../../src/hooks/useStorage.ts"],"names":[],"mappings":"AACA,OAAO,EAAqC,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAGnF,wBAAgB,UAAU,IAAI;IAC5B,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9D,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAClD,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB,CAuBA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useState, useCallback } from 'react';
|
|
2
|
+
import { uploadFile, listFiles, removeFile } from '@zveltio/sdk';
|
|
3
|
+
import { useZveltioClient } from '../context.js';
|
|
4
|
+
export function useStorage() {
|
|
5
|
+
const client = useZveltioClient();
|
|
6
|
+
const [uploading, setUploading] = useState(false);
|
|
7
|
+
const [error, setError] = useState(null);
|
|
8
|
+
const upload = useCallback(async (file, folder) => {
|
|
9
|
+
setUploading(true);
|
|
10
|
+
setError(null);
|
|
11
|
+
try {
|
|
12
|
+
return await uploadFile(client, file, folder);
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
16
|
+
setError(e);
|
|
17
|
+
throw e;
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
setUploading(false);
|
|
21
|
+
}
|
|
22
|
+
}, [client]);
|
|
23
|
+
const list = useCallback((folder) => listFiles(client, folder), [client]);
|
|
24
|
+
const remove = useCallback((fileId) => removeFile(client, fileId), [client]);
|
|
25
|
+
return { upload, list, remove, uploading, error };
|
|
26
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { HookResult } from '../types.js';
|
|
2
|
+
export interface UseSyncCollectionOptions {
|
|
3
|
+
realtimeUrl?: string;
|
|
4
|
+
syncInterval?: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function useSyncCollection<T = any>(collectionName: string, options?: UseSyncCollectionOptions): HookResult<T[]>;
|
|
7
|
+
//# sourceMappingURL=useSyncCollection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSyncCollection.d.ts","sourceRoot":"","sources":["../../src/hooks/useSyncCollection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,MAAM,WAAW,wBAAwB;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,GAAG,EACvC,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,wBAAwB,GACjC,UAAU,CAAC,CAAC,EAAE,CAAC,CA+BjB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useState, useEffect, useRef } from 'react';
|
|
2
|
+
import { SyncManager } from '@zveltio/sdk';
|
|
3
|
+
import { useZveltioClient } from '../context.js';
|
|
4
|
+
export function useSyncCollection(collectionName, options) {
|
|
5
|
+
const client = useZveltioClient();
|
|
6
|
+
const [data, setData] = useState(null);
|
|
7
|
+
const [loading, setLoading] = useState(true);
|
|
8
|
+
const [error, setError] = useState(null);
|
|
9
|
+
const syncRef = useRef(null);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const sync = new SyncManager(client, {
|
|
12
|
+
syncInterval: options?.syncInterval,
|
|
13
|
+
});
|
|
14
|
+
syncRef.current = sync;
|
|
15
|
+
sync.start(options?.realtimeUrl).then(() => {
|
|
16
|
+
const unsub = sync.collection(collectionName).subscribe((records) => {
|
|
17
|
+
setData(records);
|
|
18
|
+
setLoading(false);
|
|
19
|
+
});
|
|
20
|
+
return unsub;
|
|
21
|
+
}).catch((err) => {
|
|
22
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
23
|
+
setLoading(false);
|
|
24
|
+
});
|
|
25
|
+
return () => {
|
|
26
|
+
sync.stop();
|
|
27
|
+
syncRef.current = null;
|
|
28
|
+
};
|
|
29
|
+
}, [client, collectionName]);
|
|
30
|
+
return { data, loading, error };
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSyncStatus.d.ts","sourceRoot":"","sources":["../../src/hooks/useSyncStatus.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,wBAAgB,aAAa,CAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,cAAc,SAAO,GACpB,UAAU,CAiDZ"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import { useZveltioClient } from '../context.js';
|
|
3
|
+
export function useSyncStatus(syncManager, pollIntervalMs = 2000) {
|
|
4
|
+
const client = useZveltioClient();
|
|
5
|
+
const [status, setStatus] = useState({
|
|
6
|
+
status: 'online',
|
|
7
|
+
pendingCount: 0,
|
|
8
|
+
});
|
|
9
|
+
// If no syncManager passed in, use the client's online state via navigator
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (!syncManager) {
|
|
12
|
+
const updateOnline = () => setStatus((s) => ({
|
|
13
|
+
...s,
|
|
14
|
+
status: (typeof navigator !== 'undefined' && !navigator.onLine)
|
|
15
|
+
? 'offline'
|
|
16
|
+
: 'online',
|
|
17
|
+
}));
|
|
18
|
+
if (typeof window !== 'undefined') {
|
|
19
|
+
window.addEventListener('online', updateOnline);
|
|
20
|
+
window.addEventListener('offline', updateOnline);
|
|
21
|
+
updateOnline();
|
|
22
|
+
}
|
|
23
|
+
return () => {
|
|
24
|
+
if (typeof window !== 'undefined') {
|
|
25
|
+
window.removeEventListener('online', updateOnline);
|
|
26
|
+
window.removeEventListener('offline', updateOnline);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const poll = async () => {
|
|
31
|
+
try {
|
|
32
|
+
const s = await syncManager.getStatus();
|
|
33
|
+
setStatus({
|
|
34
|
+
status: s.isOnline ? (s.pending > 0 ? 'syncing' : 'online') : 'offline',
|
|
35
|
+
pendingCount: s.pending,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
/* ignore */
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
poll();
|
|
43
|
+
const timer = setInterval(poll, pollIntervalMs);
|
|
44
|
+
return () => clearInterval(timer);
|
|
45
|
+
}, [syncManager, pollIntervalMs]);
|
|
46
|
+
return status;
|
|
47
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { ZveltioProvider, useZveltioClient } from './context.js';
|
|
2
|
+
export { useCollection } from './hooks/useCollection.js';
|
|
3
|
+
export { useRecord } from './hooks/useRecord.js';
|
|
4
|
+
export { useSyncCollection } from './hooks/useSyncCollection.js';
|
|
5
|
+
export { useSyncStatus } from './hooks/useSyncStatus.js';
|
|
6
|
+
export { useRealtime } from './hooks/useRealtime.js';
|
|
7
|
+
export { useAuth } from './hooks/useAuth.js';
|
|
8
|
+
export { useStorage } from './hooks/useStorage.js';
|
|
9
|
+
export type { CollectionOptions, HookResult, SyncStatus } from './types.js';
|
|
10
|
+
export type { ZveltioProviderProps } from './context.js';
|
|
11
|
+
export type { UseSyncCollectionOptions } from './hooks/useSyncCollection.js';
|
|
12
|
+
export type { AuthState } from './hooks/useAuth.js';
|
|
13
|
+
export type { StorageFile } from '@zveltio/sdk';
|
|
14
|
+
export { ZveltioClient, createZveltioClient } from '@zveltio/sdk';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5E,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,YAAY,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAC7E,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { ZveltioProvider, useZveltioClient } from './context.js';
|
|
2
|
+
export { useCollection } from './hooks/useCollection.js';
|
|
3
|
+
export { useRecord } from './hooks/useRecord.js';
|
|
4
|
+
export { useSyncCollection } from './hooks/useSyncCollection.js';
|
|
5
|
+
export { useSyncStatus } from './hooks/useSyncStatus.js';
|
|
6
|
+
export { useRealtime } from './hooks/useRealtime.js';
|
|
7
|
+
export { useAuth } from './hooks/useAuth.js';
|
|
8
|
+
export { useStorage } from './hooks/useStorage.js';
|
|
9
|
+
// Re-export core client for convenience
|
|
10
|
+
export { ZveltioClient, createZveltioClient } from '@zveltio/sdk';
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface CollectionOptions {
|
|
2
|
+
filter?: Record<string, any>;
|
|
3
|
+
sort?: string;
|
|
4
|
+
order?: 'asc' | 'desc';
|
|
5
|
+
limit?: number;
|
|
6
|
+
page?: number;
|
|
7
|
+
search?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface HookResult<T> {
|
|
10
|
+
data: T | null;
|
|
11
|
+
loading: boolean;
|
|
12
|
+
error: Error | null;
|
|
13
|
+
}
|
|
14
|
+
export interface SyncStatus {
|
|
15
|
+
status: 'online' | 'offline' | 'syncing';
|
|
16
|
+
pendingCount: number;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IACzC,YAAY,EAAE,MAAM,CAAC;CACtB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zveltio/react",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"dev": "tsc --watch",
|
|
20
|
+
"typecheck": "tsc --noEmit"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@zveltio/sdk": "1.2.0"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"react": ">=18",
|
|
27
|
+
"react-dom": ">=18"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/react": "^18.0.0",
|
|
31
|
+
"@types/react-dom": "^18.0.0",
|
|
32
|
+
"typescript": "^5.4.0"
|
|
33
|
+
}
|
|
34
|
+
}
|