@snackbase/sdk 0.1.1 → 0.3.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/dist/index.cjs +2835 -0
- package/dist/{index-Dr6K4PMl.d.mts → index.d.cts} +367 -38
- package/dist/index.d.mts +2447 -2
- package/dist/index.mjs +357 -56
- package/package.json +33 -38
- package/CHANGELOG.md +0 -61
- package/README.md +0 -287
- package/dist/react/index.d.mts +0 -63
- package/dist/react/index.mjs +0 -271
package/CHANGELOG.md
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
|
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
-
|
|
8
|
-
## [Unreleased]
|
|
9
|
-
|
|
10
|
-
### Added
|
|
11
|
-
- Initial release of SnackBase SDK for JavaScript/TypeScript
|
|
12
|
-
|
|
13
|
-
### Features
|
|
14
|
-
- **Core Client**: `SnackBaseClient` with configuration validation
|
|
15
|
-
- **HTTP Client**: Fetch-based HTTP client with interceptors
|
|
16
|
-
- **Authentication**: Email/password, OAuth, SAML, and API key authentication
|
|
17
|
-
- **Services**: 17+ service classes for all SnackBase resources
|
|
18
|
-
- Accounts, Users, Collections, Records
|
|
19
|
-
- Roles, Collection Rules (Permission System V2)
|
|
20
|
-
- Groups, Invitations, Macros
|
|
21
|
-
- API Keys, Audit Logs, Dashboard, Admin
|
|
22
|
-
- Email Templates, Files
|
|
23
|
-
- **Real-Time**: WebSocket/SSE support with automatic reconnection
|
|
24
|
-
- **Query Builder**: Fluent API for complex queries
|
|
25
|
-
- **React Integration**: Context provider and hooks
|
|
26
|
-
- `useAuth`, `useQuery`, `useRecord`, `useMutation`, `useSubscription`
|
|
27
|
-
- **Type Safety**: Complete TypeScript definitions
|
|
28
|
-
- **Error Handling**: Typed error hierarchy
|
|
29
|
-
- **Storage Abstraction**: Platform-agnostic storage backends
|
|
30
|
-
- **Logging**: Structured logging system with configurable levels
|
|
31
|
-
|
|
32
|
-
### Package Exports
|
|
33
|
-
- `@snackbase/sdk` - Core SDK
|
|
34
|
-
- `@snackbase/sdk/react` - React integration
|
|
35
|
-
|
|
36
|
-
### Build Output
|
|
37
|
-
- ESM (`.mjs`) - 14.87 KB gzipped
|
|
38
|
-
- CommonJS (`.js`)
|
|
39
|
-
- TypeScript declarations (`.d.ts`)
|
|
40
|
-
|
|
41
|
-
## [0.1.0] - 2025-01-XX
|
|
42
|
-
|
|
43
|
-
### Added
|
|
44
|
-
- Initial beta release
|
|
45
|
-
- Complete Phase 1-4 implementation
|
|
46
|
-
- Core SDK features
|
|
47
|
-
- React hooks
|
|
48
|
-
- Real-time subscriptions
|
|
49
|
-
- Query builder
|
|
50
|
-
- 231 tests passing
|
|
51
|
-
|
|
52
|
-
## [Future Releases]
|
|
53
|
-
|
|
54
|
-
### Planned
|
|
55
|
-
- Integration tests with test server
|
|
56
|
-
- Performance benchmarks
|
|
57
|
-
- Request deduplication
|
|
58
|
-
- Advanced caching strategies
|
|
59
|
-
- Vue 3 integration
|
|
60
|
-
- Angular integration
|
|
61
|
-
- Svelte integration
|
package/README.md
DELETED
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
# SnackBase SDK
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/@snackbase/sdk)
|
|
4
|
-
[](https://opensource.org/licenses/MIT)
|
|
5
|
-
[](https://github.com/snackbase/snackbase-js/actions)
|
|
6
|
-
|
|
7
|
-
The official JavaScript/TypeScript SDK for [SnackBase](https://snackbase.dev) - a powerful backend-as-a-service platform.
|
|
8
|
-
|
|
9
|
-
## Features
|
|
10
|
-
|
|
11
|
-
- **Type-Safe**: Built with TypeScript for full type safety and excellent developer experience
|
|
12
|
-
- **Authentication**: Support for JWT tokens, OAuth, SAML, and API keys
|
|
13
|
-
- **Real-Time**: WebSocket and SSE support for real-time data synchronization
|
|
14
|
-
- **React Integration**: Dedicated React hooks and context for seamless integration
|
|
15
|
-
- **Query Builder**: Fluent API for building complex queries with filtering, sorting, and pagination
|
|
16
|
-
- **Platform Agnostic**: Works in browsers, React Native, and Node.js
|
|
17
|
-
- **Lightweight**: Only 14.87 KB gzipped for the core SDK
|
|
18
|
-
|
|
19
|
-
## Installation
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
# npm
|
|
23
|
-
npm install @snackbase/sdk
|
|
24
|
-
|
|
25
|
-
# yarn
|
|
26
|
-
yarn add @snackbase/sdk
|
|
27
|
-
|
|
28
|
-
# pnpm
|
|
29
|
-
pnpm add @snackbase/sdk
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### React Integration
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
# npm
|
|
36
|
-
npm install @snackbase/sdk react
|
|
37
|
-
|
|
38
|
-
# yarn
|
|
39
|
-
yarn add @snackbase/sdk react
|
|
40
|
-
|
|
41
|
-
# pnpm
|
|
42
|
-
pnpm add @snackbase/sdk react
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Quick Start
|
|
46
|
-
|
|
47
|
-
### Basic Usage
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
import { SnackBaseClient } from "@snackbase/sdk";
|
|
51
|
-
|
|
52
|
-
// Initialize the client
|
|
53
|
-
const client = new SnackBaseClient({
|
|
54
|
-
baseUrl: "https://your-project.snackbase.dev",
|
|
55
|
-
apiKey: "your-api-key", // Optional for public access
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
// Authenticate with email/password
|
|
59
|
-
const auth = await client.auth.authenticateWithPassword({
|
|
60
|
-
email: "user@example.com",
|
|
61
|
-
password: "password123",
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
console.log("Logged in as:", auth.user.email);
|
|
65
|
-
|
|
66
|
-
// List records from a collection
|
|
67
|
-
const records = await client.records.list("posts", {
|
|
68
|
-
filter: { status: "published" },
|
|
69
|
-
sort: "-createdAt",
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
// Subscribe to real-time updates
|
|
73
|
-
client.realtime.subscribe("posts", (event) => {
|
|
74
|
-
console.log("New event:", event.action, event.record);
|
|
75
|
-
});
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### React Integration
|
|
79
|
-
|
|
80
|
-
```tsx
|
|
81
|
-
import { SnackBaseProvider, useAuth, useRecord } from "@snackbase/sdk/react";
|
|
82
|
-
|
|
83
|
-
function App() {
|
|
84
|
-
return (
|
|
85
|
-
<SnackBaseProvider
|
|
86
|
-
baseUrl="https://your-project.snackbase.dev"
|
|
87
|
-
apiKey="your-api-key"
|
|
88
|
-
>
|
|
89
|
-
<Posts />
|
|
90
|
-
</SnackBaseProvider>
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function Posts() {
|
|
95
|
-
const { user, login, logout } = useAuth();
|
|
96
|
-
const { data: posts, loading } = useRecord("posts", {
|
|
97
|
-
filter: { status: "published" },
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
if (!user) {
|
|
101
|
-
return <button onClick={() => login(email, password)}>Login</button>;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return (
|
|
105
|
-
<div>
|
|
106
|
-
<button onClick={logout}>Logout</button>
|
|
107
|
-
{loading ? <p>Loading...</p> : <PostList posts={posts?.items} />}
|
|
108
|
-
</div>
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
## Documentation
|
|
114
|
-
|
|
115
|
-
- [Getting Started Guide](./docs/getting-started.md)
|
|
116
|
-
- [Authentication Guide](./docs/authentication.md)
|
|
117
|
-
- [Real-Time Features](./docs/realtime.md)
|
|
118
|
-
- [React Integration](./docs/react-integration.md)
|
|
119
|
-
- [API Reference](./docs/api-reference.md)
|
|
120
|
-
- [Migration Guides](./docs/migration/)
|
|
121
|
-
|
|
122
|
-
## Platform Support
|
|
123
|
-
|
|
124
|
-
| Platform | Support |
|
|
125
|
-
| --------------------------------------- | ------- |
|
|
126
|
-
| Browser (Chrome, Firefox, Safari, Edge) | ✅ Full |
|
|
127
|
-
| React Native | ✅ Full |
|
|
128
|
-
| Node.js | ✅ Full |
|
|
129
|
-
| Next.js | ✅ Full |
|
|
130
|
-
| Vue/Nuxt | ✅ Full |
|
|
131
|
-
|
|
132
|
-
## Authentication Methods
|
|
133
|
-
|
|
134
|
-
| Method | Description |
|
|
135
|
-
| ------------------ | -------------------------------------------------- |
|
|
136
|
-
| **Email/Password** | Traditional authentication with email and password |
|
|
137
|
-
| **OAuth** | Sign in with Google, GitHub, etc. |
|
|
138
|
-
| **SAML** | Enterprise SSO support |
|
|
139
|
-
| **API Key** | Server-to-server authentication |
|
|
140
|
-
|
|
141
|
-
## Core Services
|
|
142
|
-
|
|
143
|
-
The SDK provides 17+ services for interacting with SnackBase:
|
|
144
|
-
|
|
145
|
-
- `client.auth` - Authentication and user management
|
|
146
|
-
- `client.users` - User CRUD operations
|
|
147
|
-
- `client.accounts` - Account management
|
|
148
|
-
- `client.collections` - Collection/schema management
|
|
149
|
-
- `client.records` - Dynamic record operations (CRUD, queries)
|
|
150
|
-
- `client.roles` - Role-based access control
|
|
151
|
-
- `client.groups` - Group management
|
|
152
|
-
- `client.invitations` - User invitations
|
|
153
|
-
- `client.macros` - Macro operations
|
|
154
|
-
- `client.apiKeys` - API key management
|
|
155
|
-
- `client.auditLogs` - Audit log access
|
|
156
|
-
- `client.dashboard` - Dashboard metrics
|
|
157
|
-
- `client.admin` - Admin operations
|
|
158
|
-
- `client.emailTemplates` - Email template management
|
|
159
|
-
- `client.files` - File upload/download
|
|
160
|
-
- `client.realtime` - Real-time subscriptions
|
|
161
|
-
- `client.query` - Query builder
|
|
162
|
-
|
|
163
|
-
## Query Builder
|
|
164
|
-
|
|
165
|
-
Build complex queries with a fluent API:
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
const results = await client
|
|
169
|
-
.query("posts")
|
|
170
|
-
.select("id", "title", "author.name")
|
|
171
|
-
.expand("author", "comments")
|
|
172
|
-
.filter("status", "=", "published")
|
|
173
|
-
.filter("createdAt", ">", "2024-01-01")
|
|
174
|
-
.sort("createdAt", "desc")
|
|
175
|
-
.page(1)
|
|
176
|
-
.perPage(20)
|
|
177
|
-
.execute();
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## Real-Time Subscriptions
|
|
181
|
-
|
|
182
|
-
Subscribe to record changes in real-time:
|
|
183
|
-
|
|
184
|
-
```typescript
|
|
185
|
-
// Subscribe to a collection
|
|
186
|
-
const unsubscribe = client.realtime.subscribe("posts", (event) => {
|
|
187
|
-
switch (event.action) {
|
|
188
|
-
case "create":
|
|
189
|
-
console.log("New post created:", event.record);
|
|
190
|
-
break;
|
|
191
|
-
case "update":
|
|
192
|
-
console.log("Post updated:", event.record);
|
|
193
|
-
break;
|
|
194
|
-
case "delete":
|
|
195
|
-
console.log("Post deleted:", event.record);
|
|
196
|
-
break;
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
// Unsubscribe when done
|
|
201
|
-
unsubscribe();
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
## Error Handling
|
|
205
|
-
|
|
206
|
-
The SDK provides typed errors for comprehensive error handling:
|
|
207
|
-
|
|
208
|
-
```typescript
|
|
209
|
-
import {
|
|
210
|
-
SnackBaseError,
|
|
211
|
-
AuthenticationError,
|
|
212
|
-
ValidationError,
|
|
213
|
-
NetworkError,
|
|
214
|
-
} from "@snackbase/sdk";
|
|
215
|
-
|
|
216
|
-
try {
|
|
217
|
-
await client.records.create("posts", data);
|
|
218
|
-
} catch (error) {
|
|
219
|
-
if (error instanceof ValidationError) {
|
|
220
|
-
console.error("Validation failed:", error.fields);
|
|
221
|
-
} else if (error instanceof AuthenticationError) {
|
|
222
|
-
console.error("Authentication failed:", error.message);
|
|
223
|
-
} else if (error instanceof NetworkError) {
|
|
224
|
-
console.error("Network error:", error.message);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
## TypeScript Support
|
|
230
|
-
|
|
231
|
-
The SDK is written in TypeScript and provides full type definitions:
|
|
232
|
-
|
|
233
|
-
```typescript
|
|
234
|
-
import type { User, Post, Comment } from "@snackbase/sdk";
|
|
235
|
-
|
|
236
|
-
// Type-safe record operations
|
|
237
|
-
const post: Post = await client.records.get<Post>("posts", "record-id");
|
|
238
|
-
|
|
239
|
-
// Type-safe auth state
|
|
240
|
-
const user: User = await client.auth.getCurrentUser();
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
## Development
|
|
244
|
-
|
|
245
|
-
```bash
|
|
246
|
-
# Clone the repository
|
|
247
|
-
git clone https://github.com/snackbase/snackbase-js.git
|
|
248
|
-
cd snackbase-js
|
|
249
|
-
|
|
250
|
-
# Install dependencies
|
|
251
|
-
npm install
|
|
252
|
-
|
|
253
|
-
# Build
|
|
254
|
-
npm run build
|
|
255
|
-
|
|
256
|
-
# Run tests
|
|
257
|
-
npm test
|
|
258
|
-
|
|
259
|
-
# Watch mode
|
|
260
|
-
npm run dev
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
## Bundle Size
|
|
264
|
-
|
|
265
|
-
- Core SDK: **14.87 KB** (gzipped)
|
|
266
|
-
- React Integration: **1.42 KB** (gzipped)
|
|
267
|
-
- Total: **16.29 KB** (gzipped)
|
|
268
|
-
|
|
269
|
-
## License
|
|
270
|
-
|
|
271
|
-
MIT © [SnackBase](https://snackbase.dev)
|
|
272
|
-
|
|
273
|
-
## Contributing
|
|
274
|
-
|
|
275
|
-
We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) for details.
|
|
276
|
-
|
|
277
|
-
## Support
|
|
278
|
-
|
|
279
|
-
- Documentation: [https://docs.snackbase.dev](https://docs.snackbase.dev)
|
|
280
|
-
- GitHub Issues: [https://github.com/snackbase/snackbase-js/issues](https://github.com/snackbase/snackbase-js/issues)
|
|
281
|
-
- Discord: [https://discord.gg/snackbase](https://discord.gg/snackbase)
|
|
282
|
-
|
|
283
|
-
## Related Projects
|
|
284
|
-
|
|
285
|
-
- [SnackBase](https://snackbase.dev) - The official SnackBase platform
|
|
286
|
-
- [snackbase-python](https://github.com/snackbase/snackbase-python) - Python SDK
|
|
287
|
-
- [snackbase-go](https://github.com/snackbase/snackbase-go) - Go SDK
|
package/dist/react/index.d.mts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { Ft as PasswordResetRequest, It as RegisterData, Ot as AuthState, Pt as PasswordResetConfirm, _t as BaseRecord, kt as LoginCredentials, s as SnackBaseClient, vt as RecordListParams, yt as RecordListResponse } from "../index-Dr6K4PMl.mjs";
|
|
2
|
-
import React from "react";
|
|
3
|
-
|
|
4
|
-
//#region src/react/SnackBaseContext.d.ts
|
|
5
|
-
interface SnackBaseProviderProps {
|
|
6
|
-
client: SnackBaseClient;
|
|
7
|
-
children: React.ReactNode;
|
|
8
|
-
}
|
|
9
|
-
declare const SnackBaseProvider: React.FC<SnackBaseProviderProps>;
|
|
10
|
-
declare const useSnackBase: () => SnackBaseClient;
|
|
11
|
-
//#endregion
|
|
12
|
-
//#region src/react/hooks/useAuth.d.ts
|
|
13
|
-
interface UseAuthResult extends AuthState {
|
|
14
|
-
login: (credentials: LoginCredentials) => Promise<any>;
|
|
15
|
-
logout: () => Promise<void>;
|
|
16
|
-
register: (data: RegisterData) => Promise<any>;
|
|
17
|
-
forgotPassword: (data: PasswordResetRequest) => Promise<any>;
|
|
18
|
-
resetPassword: (data: PasswordResetConfirm) => Promise<any>;
|
|
19
|
-
isLoading: boolean;
|
|
20
|
-
}
|
|
21
|
-
declare const useAuth: () => UseAuthResult;
|
|
22
|
-
//#endregion
|
|
23
|
-
//#region src/react/hooks/useQuery.d.ts
|
|
24
|
-
interface UseQueryResult<T> {
|
|
25
|
-
data: RecordListResponse<T> | null;
|
|
26
|
-
loading: boolean;
|
|
27
|
-
error: Error | null;
|
|
28
|
-
refetch: () => Promise<void>;
|
|
29
|
-
}
|
|
30
|
-
declare const useQuery: <T = any>(collection: string, params?: RecordListParams) => UseQueryResult<T>;
|
|
31
|
-
//#endregion
|
|
32
|
-
//#region src/react/hooks/useRecord.d.ts
|
|
33
|
-
interface UseRecordResult<T> {
|
|
34
|
-
data: (T & BaseRecord) | null;
|
|
35
|
-
loading: boolean;
|
|
36
|
-
error: Error | null;
|
|
37
|
-
refetch: () => Promise<void>;
|
|
38
|
-
}
|
|
39
|
-
interface UseRecordOptions {
|
|
40
|
-
fields?: string[] | string;
|
|
41
|
-
expand?: string[] | string;
|
|
42
|
-
}
|
|
43
|
-
declare const useRecord: <T = any>(collection: string, id: string, options?: UseRecordOptions) => UseRecordResult<T>;
|
|
44
|
-
//#endregion
|
|
45
|
-
//#region src/react/hooks/useMutation.d.ts
|
|
46
|
-
interface UseMutationResult<T> {
|
|
47
|
-
create: (data: Partial<T>) => Promise<T & BaseRecord>;
|
|
48
|
-
update: (id: string, data: Partial<T>) => Promise<T & BaseRecord>;
|
|
49
|
-
del: (id: string) => Promise<boolean>;
|
|
50
|
-
loading: boolean;
|
|
51
|
-
error: Error | null;
|
|
52
|
-
}
|
|
53
|
-
declare const useMutation: <T = any>(collection: string) => UseMutationResult<T>;
|
|
54
|
-
//#endregion
|
|
55
|
-
//#region src/react/hooks/useSubscription.d.ts
|
|
56
|
-
interface UseSubscriptionResult {
|
|
57
|
-
connected: boolean;
|
|
58
|
-
error: Error | null;
|
|
59
|
-
}
|
|
60
|
-
declare const useSubscription: <T = any>(collection: string, event: string, // e.g., 'create', 'update', 'delete', '*'
|
|
61
|
-
callback: (data: any) => void) => UseSubscriptionResult;
|
|
62
|
-
//#endregion
|
|
63
|
-
export { SnackBaseProvider, SnackBaseProviderProps, UseAuthResult, UseMutationResult, UseQueryResult, UseRecordOptions, UseRecordResult, UseSubscriptionResult, useAuth, useMutation, useQuery, useRecord, useSnackBase, useSubscription };
|
package/dist/react/index.mjs
DELETED
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
2
|
-
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
|
|
4
|
-
//#region src/react/SnackBaseContext.tsx
|
|
5
|
-
const SnackBaseContext = createContext(null);
|
|
6
|
-
const SnackBaseProvider = ({ client, children }) => {
|
|
7
|
-
return /* @__PURE__ */ jsx(SnackBaseContext.Provider, {
|
|
8
|
-
value: client,
|
|
9
|
-
children
|
|
10
|
-
});
|
|
11
|
-
};
|
|
12
|
-
const useSnackBase = () => {
|
|
13
|
-
const context = useContext(SnackBaseContext);
|
|
14
|
-
if (!context) throw new Error("useSnackBase must be used within a SnackBaseProvider");
|
|
15
|
-
return context;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
//#endregion
|
|
19
|
-
//#region src/react/hooks/useAuth.ts
|
|
20
|
-
const useAuth = () => {
|
|
21
|
-
const client = useSnackBase();
|
|
22
|
-
const [state, setState] = useState({
|
|
23
|
-
user: client.user,
|
|
24
|
-
account: client.account,
|
|
25
|
-
token: client.auth.token,
|
|
26
|
-
refreshToken: client.auth.refreshToken,
|
|
27
|
-
isAuthenticated: client.isAuthenticated,
|
|
28
|
-
expiresAt: null
|
|
29
|
-
});
|
|
30
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
setState({
|
|
33
|
-
user: client.user,
|
|
34
|
-
account: client.account,
|
|
35
|
-
token: client.auth.token,
|
|
36
|
-
refreshToken: client.auth.refreshToken,
|
|
37
|
-
isAuthenticated: client.isAuthenticated,
|
|
38
|
-
expiresAt: null
|
|
39
|
-
});
|
|
40
|
-
const updateState = (newState) => {
|
|
41
|
-
setState(newState);
|
|
42
|
-
};
|
|
43
|
-
const clearState = () => {
|
|
44
|
-
setState({
|
|
45
|
-
user: null,
|
|
46
|
-
account: null,
|
|
47
|
-
token: null,
|
|
48
|
-
refreshToken: null,
|
|
49
|
-
isAuthenticated: false,
|
|
50
|
-
expiresAt: null
|
|
51
|
-
});
|
|
52
|
-
};
|
|
53
|
-
const unsubscribeLogin = client.on("auth:login", updateState);
|
|
54
|
-
const unsubscribeRefresh = client.on("auth:refresh", updateState);
|
|
55
|
-
const unsubscribeLogout = client.on("auth:logout", clearState);
|
|
56
|
-
return () => {
|
|
57
|
-
unsubscribeLogin();
|
|
58
|
-
unsubscribeRefresh();
|
|
59
|
-
unsubscribeLogout();
|
|
60
|
-
};
|
|
61
|
-
}, [client]);
|
|
62
|
-
const login = useCallback(async (credentials) => {
|
|
63
|
-
setIsLoading(true);
|
|
64
|
-
try {
|
|
65
|
-
return await client.login(credentials);
|
|
66
|
-
} finally {
|
|
67
|
-
setIsLoading(false);
|
|
68
|
-
}
|
|
69
|
-
}, [client]);
|
|
70
|
-
const logout = useCallback(async () => {
|
|
71
|
-
setIsLoading(true);
|
|
72
|
-
try {
|
|
73
|
-
await client.logout();
|
|
74
|
-
} finally {
|
|
75
|
-
setIsLoading(false);
|
|
76
|
-
}
|
|
77
|
-
}, [client]);
|
|
78
|
-
const register = useCallback(async (data) => {
|
|
79
|
-
setIsLoading(true);
|
|
80
|
-
try {
|
|
81
|
-
return await client.register(data);
|
|
82
|
-
} finally {
|
|
83
|
-
setIsLoading(false);
|
|
84
|
-
}
|
|
85
|
-
}, [client]);
|
|
86
|
-
const forgotPassword = useCallback(async (data) => {
|
|
87
|
-
setIsLoading(true);
|
|
88
|
-
try {
|
|
89
|
-
return await client.forgotPassword(data);
|
|
90
|
-
} finally {
|
|
91
|
-
setIsLoading(false);
|
|
92
|
-
}
|
|
93
|
-
}, [client]);
|
|
94
|
-
const resetPassword = useCallback(async (data) => {
|
|
95
|
-
setIsLoading(true);
|
|
96
|
-
try {
|
|
97
|
-
return await client.resetPassword(data);
|
|
98
|
-
} finally {
|
|
99
|
-
setIsLoading(false);
|
|
100
|
-
}
|
|
101
|
-
}, [client]);
|
|
102
|
-
return {
|
|
103
|
-
...state,
|
|
104
|
-
login,
|
|
105
|
-
logout,
|
|
106
|
-
register,
|
|
107
|
-
forgotPassword,
|
|
108
|
-
resetPassword,
|
|
109
|
-
isLoading
|
|
110
|
-
};
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
//#endregion
|
|
114
|
-
//#region src/react/hooks/useQuery.ts
|
|
115
|
-
const useQuery = (collection, params) => {
|
|
116
|
-
const client = useSnackBase();
|
|
117
|
-
const [data, setData] = useState(null);
|
|
118
|
-
const [loading, setLoading] = useState(true);
|
|
119
|
-
const [error, setError] = useState(null);
|
|
120
|
-
const paramsKey = JSON.stringify(params);
|
|
121
|
-
const paramsRef = useRef(params);
|
|
122
|
-
if (JSON.stringify(paramsRef.current) !== paramsKey) paramsRef.current = params;
|
|
123
|
-
const fetchData = useCallback(async () => {
|
|
124
|
-
setLoading(true);
|
|
125
|
-
setError(null);
|
|
126
|
-
try {
|
|
127
|
-
setData(await client.records.list(collection, paramsRef.current));
|
|
128
|
-
} catch (err) {
|
|
129
|
-
setError(err);
|
|
130
|
-
} finally {
|
|
131
|
-
setLoading(false);
|
|
132
|
-
}
|
|
133
|
-
}, [
|
|
134
|
-
client,
|
|
135
|
-
collection,
|
|
136
|
-
paramsKey
|
|
137
|
-
]);
|
|
138
|
-
useEffect(() => {
|
|
139
|
-
fetchData();
|
|
140
|
-
}, [fetchData]);
|
|
141
|
-
return {
|
|
142
|
-
data,
|
|
143
|
-
loading,
|
|
144
|
-
error,
|
|
145
|
-
refetch: fetchData
|
|
146
|
-
};
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
//#endregion
|
|
150
|
-
//#region src/react/hooks/useRecord.ts
|
|
151
|
-
const useRecord = (collection, id, options) => {
|
|
152
|
-
const client = useSnackBase();
|
|
153
|
-
const [data, setData] = useState(null);
|
|
154
|
-
const [loading, setLoading] = useState(true);
|
|
155
|
-
const [error, setError] = useState(null);
|
|
156
|
-
const fetchData = useCallback(async () => {
|
|
157
|
-
if (!id) return;
|
|
158
|
-
setLoading(true);
|
|
159
|
-
setError(null);
|
|
160
|
-
try {
|
|
161
|
-
setData(await client.records.get(collection, id, options));
|
|
162
|
-
} catch (err) {
|
|
163
|
-
setError(err);
|
|
164
|
-
} finally {
|
|
165
|
-
setLoading(false);
|
|
166
|
-
}
|
|
167
|
-
}, [
|
|
168
|
-
client,
|
|
169
|
-
collection,
|
|
170
|
-
id,
|
|
171
|
-
JSON.stringify(options)
|
|
172
|
-
]);
|
|
173
|
-
useEffect(() => {
|
|
174
|
-
fetchData();
|
|
175
|
-
}, [fetchData]);
|
|
176
|
-
return {
|
|
177
|
-
data,
|
|
178
|
-
loading,
|
|
179
|
-
error,
|
|
180
|
-
refetch: fetchData
|
|
181
|
-
};
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
//#endregion
|
|
185
|
-
//#region src/react/hooks/useMutation.ts
|
|
186
|
-
const useMutation = (collection) => {
|
|
187
|
-
const client = useSnackBase();
|
|
188
|
-
const [loading, setLoading] = useState(false);
|
|
189
|
-
const [error, setError] = useState(null);
|
|
190
|
-
return {
|
|
191
|
-
create: useCallback(async (data) => {
|
|
192
|
-
setLoading(true);
|
|
193
|
-
setError(null);
|
|
194
|
-
try {
|
|
195
|
-
return await client.records.create(collection, data);
|
|
196
|
-
} catch (err) {
|
|
197
|
-
setError(err);
|
|
198
|
-
throw err;
|
|
199
|
-
} finally {
|
|
200
|
-
setLoading(false);
|
|
201
|
-
}
|
|
202
|
-
}, [client, collection]),
|
|
203
|
-
update: useCallback(async (id, data) => {
|
|
204
|
-
setLoading(true);
|
|
205
|
-
setError(null);
|
|
206
|
-
try {
|
|
207
|
-
return await client.records.update(collection, id, data);
|
|
208
|
-
} catch (err) {
|
|
209
|
-
setError(err);
|
|
210
|
-
throw err;
|
|
211
|
-
} finally {
|
|
212
|
-
setLoading(false);
|
|
213
|
-
}
|
|
214
|
-
}, [client, collection]),
|
|
215
|
-
del: useCallback(async (id) => {
|
|
216
|
-
setLoading(true);
|
|
217
|
-
setError(null);
|
|
218
|
-
try {
|
|
219
|
-
await client.records.delete(collection, id);
|
|
220
|
-
return true;
|
|
221
|
-
} catch (err) {
|
|
222
|
-
setError(err);
|
|
223
|
-
throw err;
|
|
224
|
-
} finally {
|
|
225
|
-
setLoading(false);
|
|
226
|
-
}
|
|
227
|
-
}, [client, collection]),
|
|
228
|
-
loading,
|
|
229
|
-
error
|
|
230
|
-
};
|
|
231
|
-
};
|
|
232
|
-
|
|
233
|
-
//#endregion
|
|
234
|
-
//#region src/react/hooks/useSubscription.ts
|
|
235
|
-
const useSubscription = (collection, event, callback) => {
|
|
236
|
-
const client = useSnackBase();
|
|
237
|
-
const [connected, setConnected] = useState(false);
|
|
238
|
-
const [error, setError] = useState(null);
|
|
239
|
-
useEffect(() => {
|
|
240
|
-
let unsubscribe;
|
|
241
|
-
const setupSubscription = async () => {
|
|
242
|
-
try {
|
|
243
|
-
await client.realtime.subscribe(collection, event === "*" ? void 0 : [event]);
|
|
244
|
-
setConnected(true);
|
|
245
|
-
const eventType = event === "*" ? `${collection}.*` : `${collection}.${event}`;
|
|
246
|
-
unsubscribe = client.realtime.on(eventType, (e) => {
|
|
247
|
-
callback(e.data);
|
|
248
|
-
});
|
|
249
|
-
} catch (err) {
|
|
250
|
-
setError(err);
|
|
251
|
-
setConnected(false);
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
|
-
setupSubscription();
|
|
255
|
-
return () => {
|
|
256
|
-
if (unsubscribe) unsubscribe();
|
|
257
|
-
client.realtime.unsubscribe(collection).catch(console.error);
|
|
258
|
-
};
|
|
259
|
-
}, [
|
|
260
|
-
client,
|
|
261
|
-
collection,
|
|
262
|
-
event
|
|
263
|
-
]);
|
|
264
|
-
return {
|
|
265
|
-
connected,
|
|
266
|
-
error
|
|
267
|
-
};
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
//#endregion
|
|
271
|
-
export { SnackBaseProvider, useAuth, useMutation, useQuery, useRecord, useSnackBase, useSubscription };
|