@23blocks/react 1.1.1 → 1.1.3
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.d.ts +1 -0
- package/dist/index.esm.js +1306 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/lib/context.d.ts +114 -0
- package/dist/src/lib/context.d.ts.map +1 -0
- package/dist/src/lib/hooks/index.d.ts +5 -0
- package/dist/src/lib/hooks/index.d.ts.map +1 -0
- package/dist/src/lib/hooks/use-auth.d.ts +52 -0
- package/dist/src/lib/hooks/use-auth.d.ts.map +1 -0
- package/dist/src/lib/hooks/use-favorites.d.ts +41 -0
- package/dist/src/lib/hooks/use-favorites.d.ts.map +1 -0
- package/dist/src/lib/hooks/use-search.d.ts +55 -0
- package/dist/src/lib/hooks/use-search.d.ts.map +1 -0
- package/dist/src/lib/hooks/use-users.d.ts +44 -0
- package/dist/src/lib/hooks/use-users.d.ts.map +1 -0
- package/dist/src/lib/index.d.ts +4 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/simple-provider.d.ts +281 -0
- package/dist/src/lib/simple-provider.d.ts.map +1 -0
- package/package.json +10 -8
- package/dist/index.js +0 -3
- package/dist/index.js.map +0 -1
- package/dist/lib/context.js +0 -206
- package/dist/lib/context.js.map +0 -1
- package/dist/lib/hooks/index.js +0 -8
- package/dist/lib/hooks/index.js.map +0 -1
- package/dist/lib/hooks/use-auth.js +0 -159
- package/dist/lib/hooks/use-auth.js.map +0 -1
- package/dist/lib/hooks/use-favorites.js +0 -114
- package/dist/lib/hooks/use-favorites.js.map +0 -1
- package/dist/lib/hooks/use-search.js +0 -120
- package/dist/lib/hooks/use-search.js.map +0 -1
- package/dist/lib/hooks/use-users.js +0 -115
- package/dist/lib/hooks/use-users.js.map +0 -1
- package/dist/lib/index.js +0 -17
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/simple-provider.js +0 -620
- package/dist/lib/simple-provider.js.map +0 -1
|
@@ -0,0 +1,1306 @@
|
|
|
1
|
+
import { _ } from '@swc/helpers/_/_extends';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useMemo, useCallback, createContext, useContext, useState } from 'react';
|
|
4
|
+
import { createHttpTransport } from '@23blocks/transport-http';
|
|
5
|
+
import { createAuthenticationBlock } from '@23blocks/block-authentication';
|
|
6
|
+
import { createSearchBlock } from '@23blocks/block-search';
|
|
7
|
+
import { createProductsBlock } from '@23blocks/block-products';
|
|
8
|
+
import { createCrmBlock } from '@23blocks/block-crm';
|
|
9
|
+
import { createContentBlock } from '@23blocks/block-content';
|
|
10
|
+
import { createGeolocationBlock } from '@23blocks/block-geolocation';
|
|
11
|
+
import { createConversationsBlock } from '@23blocks/block-conversations';
|
|
12
|
+
import { createFilesBlock } from '@23blocks/block-files';
|
|
13
|
+
import { createFormsBlock } from '@23blocks/block-forms';
|
|
14
|
+
import { createAssetsBlock } from '@23blocks/block-assets';
|
|
15
|
+
import { createCampaignsBlock } from '@23blocks/block-campaigns';
|
|
16
|
+
import { createCompanyBlock } from '@23blocks/block-company';
|
|
17
|
+
import { createRewardsBlock } from '@23blocks/block-rewards';
|
|
18
|
+
import { createSalesBlock } from '@23blocks/block-sales';
|
|
19
|
+
import { createWalletBlock } from '@23blocks/block-wallet';
|
|
20
|
+
import { createJarvisBlock } from '@23blocks/block-jarvis';
|
|
21
|
+
import { createOnboardingBlock } from '@23blocks/block-onboarding';
|
|
22
|
+
import { createUniversityBlock } from '@23blocks/block-university';
|
|
23
|
+
|
|
24
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
25
|
+
// Token Manager Implementation
|
|
26
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
27
|
+
/**
|
|
28
|
+
* Generate storage key scoped to app and tenant
|
|
29
|
+
*/ function getStorageKey(type, appId, tenantId) {
|
|
30
|
+
const scope = tenantId ? `${appId}_${tenantId}` : appId;
|
|
31
|
+
return `23blocks_${scope}_${type}_token`;
|
|
32
|
+
}
|
|
33
|
+
let MemoryStorage = class MemoryStorage {
|
|
34
|
+
getItem(key) {
|
|
35
|
+
var _this_data_get;
|
|
36
|
+
return (_this_data_get = this.data.get(key)) != null ? _this_data_get : null;
|
|
37
|
+
}
|
|
38
|
+
setItem(key, value) {
|
|
39
|
+
this.data.set(key, value);
|
|
40
|
+
}
|
|
41
|
+
removeItem(key) {
|
|
42
|
+
this.data.delete(key);
|
|
43
|
+
}
|
|
44
|
+
constructor(){
|
|
45
|
+
this.data = new Map();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
function createTokenManager(appId, storageType, tenantId) {
|
|
49
|
+
const isBrowser = typeof window !== 'undefined' && typeof window.localStorage !== 'undefined';
|
|
50
|
+
const accessTokenKey = getStorageKey('access', appId, tenantId);
|
|
51
|
+
const refreshTokenKey = getStorageKey('refresh', appId, tenantId);
|
|
52
|
+
let storage;
|
|
53
|
+
if (!isBrowser) {
|
|
54
|
+
storage = new MemoryStorage();
|
|
55
|
+
} else {
|
|
56
|
+
switch(storageType){
|
|
57
|
+
case 'sessionStorage':
|
|
58
|
+
storage = window.sessionStorage;
|
|
59
|
+
break;
|
|
60
|
+
case 'memory':
|
|
61
|
+
storage = new MemoryStorage();
|
|
62
|
+
break;
|
|
63
|
+
default:
|
|
64
|
+
storage = window.localStorage;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
getAccessToken () {
|
|
69
|
+
try {
|
|
70
|
+
return storage.getItem(accessTokenKey);
|
|
71
|
+
} catch (e) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
getRefreshToken () {
|
|
76
|
+
try {
|
|
77
|
+
return storage.getItem(refreshTokenKey);
|
|
78
|
+
} catch (e) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
setTokens (accessToken, refreshToken) {
|
|
83
|
+
try {
|
|
84
|
+
storage.setItem(accessTokenKey, accessToken);
|
|
85
|
+
if (refreshToken) {
|
|
86
|
+
storage.setItem(refreshTokenKey, refreshToken);
|
|
87
|
+
}
|
|
88
|
+
} catch (e) {
|
|
89
|
+
console.warn('[23blocks] Unable to store tokens');
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
clearTokens () {
|
|
93
|
+
try {
|
|
94
|
+
storage.removeItem(accessTokenKey);
|
|
95
|
+
storage.removeItem(refreshTokenKey);
|
|
96
|
+
} catch (e) {
|
|
97
|
+
// Silently fail
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
onStorageChange (callback) {
|
|
101
|
+
// Only works in browser with localStorage/sessionStorage
|
|
102
|
+
if (!isBrowser || storageType === 'memory') {
|
|
103
|
+
// Return no-op unsubscribe for SSR/memory storage
|
|
104
|
+
return ()=>{};
|
|
105
|
+
}
|
|
106
|
+
const handler = (event)=>{
|
|
107
|
+
// Only trigger if our keys changed
|
|
108
|
+
if (event.key === accessTokenKey || event.key === refreshTokenKey) {
|
|
109
|
+
callback();
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
window.addEventListener('storage', handler);
|
|
113
|
+
// Return unsubscribe function
|
|
114
|
+
return ()=>{
|
|
115
|
+
window.removeEventListener('storage', handler);
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
121
|
+
// Context
|
|
122
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
123
|
+
const Blocks23Context = /*#__PURE__*/ createContext(null);
|
|
124
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
125
|
+
// Provider Component
|
|
126
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
127
|
+
/**
|
|
128
|
+
* Helper to create a proxy that throws when accessing unconfigured service
|
|
129
|
+
*/ function createUnconfiguredServiceProxy(serviceName, urlKey) {
|
|
130
|
+
return new Proxy({}, {
|
|
131
|
+
get (_target, prop) {
|
|
132
|
+
throw new Error(`[23blocks] Cannot access '${serviceName}.${String(prop)}': ` + `The ${serviceName} service URL is not configured. ` + `Add 'urls.${urlKey}' to your Provider configuration.`);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Provider component for 23blocks services.
|
|
138
|
+
*
|
|
139
|
+
* Wrap your app with this provider to access all 23blocks services
|
|
140
|
+
* with automatic token management.
|
|
141
|
+
*
|
|
142
|
+
* Services are only available if their URL is configured. Accessing
|
|
143
|
+
* a service without a configured URL will throw an error.
|
|
144
|
+
*
|
|
145
|
+
* @example Basic usage with multiple services
|
|
146
|
+
* ```tsx
|
|
147
|
+
* import { Provider } from '@23blocks/react';
|
|
148
|
+
*
|
|
149
|
+
* function App() {
|
|
150
|
+
* return (
|
|
151
|
+
* <Provider
|
|
152
|
+
* appId="your-app-id"
|
|
153
|
+
* urls={{
|
|
154
|
+
* authentication: 'https://gateway.23blocks.com',
|
|
155
|
+
* crm: 'https://crm.23blocks.com',
|
|
156
|
+
* products: 'https://products.23blocks.com',
|
|
157
|
+
* }}
|
|
158
|
+
* >
|
|
159
|
+
* <MyApp />
|
|
160
|
+
* </Provider>
|
|
161
|
+
* );
|
|
162
|
+
* }
|
|
163
|
+
* ```
|
|
164
|
+
*
|
|
165
|
+
* @example Cookie mode (recommended for security)
|
|
166
|
+
* ```tsx
|
|
167
|
+
* <Provider
|
|
168
|
+
* appId="your-app-id"
|
|
169
|
+
* authMode="cookie"
|
|
170
|
+
* urls={{
|
|
171
|
+
* authentication: 'https://gateway.23blocks.com',
|
|
172
|
+
* crm: 'https://crm.23blocks.com',
|
|
173
|
+
* }}
|
|
174
|
+
* >
|
|
175
|
+
* <MyApp />
|
|
176
|
+
* </Provider>
|
|
177
|
+
* ```
|
|
178
|
+
*/ function Provider({ children, urls, appId, tenantId, authMode = 'token', storage = 'localStorage', headers: staticHeaders = {}, timeout }) {
|
|
179
|
+
// Create token manager (memoized) with scoped storage keys
|
|
180
|
+
const tokenManager = useMemo(()=>authMode === 'token' ? createTokenManager(appId, storage, tenantId) : null, [
|
|
181
|
+
authMode,
|
|
182
|
+
appId,
|
|
183
|
+
storage,
|
|
184
|
+
tenantId
|
|
185
|
+
]);
|
|
186
|
+
// Factory to create transport for a specific service URL
|
|
187
|
+
const createServiceTransport = useCallback((baseUrl)=>{
|
|
188
|
+
return createHttpTransport({
|
|
189
|
+
baseUrl,
|
|
190
|
+
timeout,
|
|
191
|
+
credentials: authMode === 'cookie' ? 'include' : undefined,
|
|
192
|
+
headers: ()=>{
|
|
193
|
+
const headers = _({}, staticHeaders, {
|
|
194
|
+
appid: appId
|
|
195
|
+
});
|
|
196
|
+
if (tenantId) {
|
|
197
|
+
headers['tenant-id'] = tenantId;
|
|
198
|
+
}
|
|
199
|
+
if (authMode === 'token' && tokenManager) {
|
|
200
|
+
const token = tokenManager.getAccessToken();
|
|
201
|
+
if (token) {
|
|
202
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return headers;
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}, [
|
|
209
|
+
appId,
|
|
210
|
+
tenantId,
|
|
211
|
+
authMode,
|
|
212
|
+
staticHeaders,
|
|
213
|
+
timeout,
|
|
214
|
+
tokenManager
|
|
215
|
+
]);
|
|
216
|
+
// Create blocks (memoized) - each with its own transport (no fallback)
|
|
217
|
+
const blockConfig = useMemo(()=>({
|
|
218
|
+
appId,
|
|
219
|
+
tenantId
|
|
220
|
+
}), [
|
|
221
|
+
appId,
|
|
222
|
+
tenantId
|
|
223
|
+
]);
|
|
224
|
+
// Create blocks only if URL is configured, otherwise use proxy that throws helpful error
|
|
225
|
+
const authentication = useMemo(()=>{
|
|
226
|
+
if (!urls.authentication) {
|
|
227
|
+
return createUnconfiguredServiceProxy('authentication', 'authentication');
|
|
228
|
+
}
|
|
229
|
+
return createAuthenticationBlock(createServiceTransport(urls.authentication), blockConfig);
|
|
230
|
+
}, [
|
|
231
|
+
createServiceTransport,
|
|
232
|
+
urls.authentication,
|
|
233
|
+
blockConfig
|
|
234
|
+
]);
|
|
235
|
+
const search = useMemo(()=>{
|
|
236
|
+
if (!urls.search) {
|
|
237
|
+
return createUnconfiguredServiceProxy('search', 'search');
|
|
238
|
+
}
|
|
239
|
+
return createSearchBlock(createServiceTransport(urls.search), blockConfig);
|
|
240
|
+
}, [
|
|
241
|
+
createServiceTransport,
|
|
242
|
+
urls.search,
|
|
243
|
+
blockConfig
|
|
244
|
+
]);
|
|
245
|
+
const products = useMemo(()=>{
|
|
246
|
+
if (!urls.products) {
|
|
247
|
+
return createUnconfiguredServiceProxy('products', 'products');
|
|
248
|
+
}
|
|
249
|
+
return createProductsBlock(createServiceTransport(urls.products), blockConfig);
|
|
250
|
+
}, [
|
|
251
|
+
createServiceTransport,
|
|
252
|
+
urls.products,
|
|
253
|
+
blockConfig
|
|
254
|
+
]);
|
|
255
|
+
const crm = useMemo(()=>{
|
|
256
|
+
if (!urls.crm) {
|
|
257
|
+
return createUnconfiguredServiceProxy('crm', 'crm');
|
|
258
|
+
}
|
|
259
|
+
return createCrmBlock(createServiceTransport(urls.crm), blockConfig);
|
|
260
|
+
}, [
|
|
261
|
+
createServiceTransport,
|
|
262
|
+
urls.crm,
|
|
263
|
+
blockConfig
|
|
264
|
+
]);
|
|
265
|
+
const content = useMemo(()=>{
|
|
266
|
+
if (!urls.content) {
|
|
267
|
+
return createUnconfiguredServiceProxy('content', 'content');
|
|
268
|
+
}
|
|
269
|
+
return createContentBlock(createServiceTransport(urls.content), blockConfig);
|
|
270
|
+
}, [
|
|
271
|
+
createServiceTransport,
|
|
272
|
+
urls.content,
|
|
273
|
+
blockConfig
|
|
274
|
+
]);
|
|
275
|
+
const geolocation = useMemo(()=>{
|
|
276
|
+
if (!urls.geolocation) {
|
|
277
|
+
return createUnconfiguredServiceProxy('geolocation', 'geolocation');
|
|
278
|
+
}
|
|
279
|
+
return createGeolocationBlock(createServiceTransport(urls.geolocation), blockConfig);
|
|
280
|
+
}, [
|
|
281
|
+
createServiceTransport,
|
|
282
|
+
urls.geolocation,
|
|
283
|
+
blockConfig
|
|
284
|
+
]);
|
|
285
|
+
const conversations = useMemo(()=>{
|
|
286
|
+
if (!urls.conversations) {
|
|
287
|
+
return createUnconfiguredServiceProxy('conversations', 'conversations');
|
|
288
|
+
}
|
|
289
|
+
return createConversationsBlock(createServiceTransport(urls.conversations), blockConfig);
|
|
290
|
+
}, [
|
|
291
|
+
createServiceTransport,
|
|
292
|
+
urls.conversations,
|
|
293
|
+
blockConfig
|
|
294
|
+
]);
|
|
295
|
+
const files = useMemo(()=>{
|
|
296
|
+
if (!urls.files) {
|
|
297
|
+
return createUnconfiguredServiceProxy('files', 'files');
|
|
298
|
+
}
|
|
299
|
+
return createFilesBlock(createServiceTransport(urls.files), blockConfig);
|
|
300
|
+
}, [
|
|
301
|
+
createServiceTransport,
|
|
302
|
+
urls.files,
|
|
303
|
+
blockConfig
|
|
304
|
+
]);
|
|
305
|
+
const forms = useMemo(()=>{
|
|
306
|
+
if (!urls.forms) {
|
|
307
|
+
return createUnconfiguredServiceProxy('forms', 'forms');
|
|
308
|
+
}
|
|
309
|
+
return createFormsBlock(createServiceTransport(urls.forms), blockConfig);
|
|
310
|
+
}, [
|
|
311
|
+
createServiceTransport,
|
|
312
|
+
urls.forms,
|
|
313
|
+
blockConfig
|
|
314
|
+
]);
|
|
315
|
+
const assets = useMemo(()=>{
|
|
316
|
+
if (!urls.assets) {
|
|
317
|
+
return createUnconfiguredServiceProxy('assets', 'assets');
|
|
318
|
+
}
|
|
319
|
+
return createAssetsBlock(createServiceTransport(urls.assets), blockConfig);
|
|
320
|
+
}, [
|
|
321
|
+
createServiceTransport,
|
|
322
|
+
urls.assets,
|
|
323
|
+
blockConfig
|
|
324
|
+
]);
|
|
325
|
+
const campaigns = useMemo(()=>{
|
|
326
|
+
if (!urls.campaigns) {
|
|
327
|
+
return createUnconfiguredServiceProxy('campaigns', 'campaigns');
|
|
328
|
+
}
|
|
329
|
+
return createCampaignsBlock(createServiceTransport(urls.campaigns), blockConfig);
|
|
330
|
+
}, [
|
|
331
|
+
createServiceTransport,
|
|
332
|
+
urls.campaigns,
|
|
333
|
+
blockConfig
|
|
334
|
+
]);
|
|
335
|
+
const company = useMemo(()=>{
|
|
336
|
+
if (!urls.company) {
|
|
337
|
+
return createUnconfiguredServiceProxy('company', 'company');
|
|
338
|
+
}
|
|
339
|
+
return createCompanyBlock(createServiceTransport(urls.company), blockConfig);
|
|
340
|
+
}, [
|
|
341
|
+
createServiceTransport,
|
|
342
|
+
urls.company,
|
|
343
|
+
blockConfig
|
|
344
|
+
]);
|
|
345
|
+
const rewards = useMemo(()=>{
|
|
346
|
+
if (!urls.rewards) {
|
|
347
|
+
return createUnconfiguredServiceProxy('rewards', 'rewards');
|
|
348
|
+
}
|
|
349
|
+
return createRewardsBlock(createServiceTransport(urls.rewards), blockConfig);
|
|
350
|
+
}, [
|
|
351
|
+
createServiceTransport,
|
|
352
|
+
urls.rewards,
|
|
353
|
+
blockConfig
|
|
354
|
+
]);
|
|
355
|
+
const sales = useMemo(()=>{
|
|
356
|
+
if (!urls.sales) {
|
|
357
|
+
return createUnconfiguredServiceProxy('sales', 'sales');
|
|
358
|
+
}
|
|
359
|
+
return createSalesBlock(createServiceTransport(urls.sales), blockConfig);
|
|
360
|
+
}, [
|
|
361
|
+
createServiceTransport,
|
|
362
|
+
urls.sales,
|
|
363
|
+
blockConfig
|
|
364
|
+
]);
|
|
365
|
+
const wallet = useMemo(()=>{
|
|
366
|
+
if (!urls.wallet) {
|
|
367
|
+
return createUnconfiguredServiceProxy('wallet', 'wallet');
|
|
368
|
+
}
|
|
369
|
+
return createWalletBlock(createServiceTransport(urls.wallet), blockConfig);
|
|
370
|
+
}, [
|
|
371
|
+
createServiceTransport,
|
|
372
|
+
urls.wallet,
|
|
373
|
+
blockConfig
|
|
374
|
+
]);
|
|
375
|
+
const jarvis = useMemo(()=>{
|
|
376
|
+
if (!urls.jarvis) {
|
|
377
|
+
return createUnconfiguredServiceProxy('jarvis', 'jarvis');
|
|
378
|
+
}
|
|
379
|
+
return createJarvisBlock(createServiceTransport(urls.jarvis), blockConfig);
|
|
380
|
+
}, [
|
|
381
|
+
createServiceTransport,
|
|
382
|
+
urls.jarvis,
|
|
383
|
+
blockConfig
|
|
384
|
+
]);
|
|
385
|
+
const onboarding = useMemo(()=>{
|
|
386
|
+
if (!urls.onboarding) {
|
|
387
|
+
return createUnconfiguredServiceProxy('onboarding', 'onboarding');
|
|
388
|
+
}
|
|
389
|
+
return createOnboardingBlock(createServiceTransport(urls.onboarding), blockConfig);
|
|
390
|
+
}, [
|
|
391
|
+
createServiceTransport,
|
|
392
|
+
urls.onboarding,
|
|
393
|
+
blockConfig
|
|
394
|
+
]);
|
|
395
|
+
const university = useMemo(()=>{
|
|
396
|
+
if (!urls.university) {
|
|
397
|
+
return createUnconfiguredServiceProxy('university', 'university');
|
|
398
|
+
}
|
|
399
|
+
return createUniversityBlock(createServiceTransport(urls.university), blockConfig);
|
|
400
|
+
}, [
|
|
401
|
+
createServiceTransport,
|
|
402
|
+
urls.university,
|
|
403
|
+
blockConfig
|
|
404
|
+
]);
|
|
405
|
+
// Check if authentication is configured for auth methods
|
|
406
|
+
const isAuthConfigured = !!urls.authentication;
|
|
407
|
+
// Auth methods with automatic token management
|
|
408
|
+
const signIn = useCallback(async (request)=>{
|
|
409
|
+
if (!isAuthConfigured) {
|
|
410
|
+
throw new Error('[23blocks] Cannot call signIn: The authentication service URL is not configured. ' + "Add 'urls.authentication' to your Provider configuration.");
|
|
411
|
+
}
|
|
412
|
+
const response = await authentication.auth.signIn(request);
|
|
413
|
+
if (authMode === 'token' && tokenManager && response.accessToken) {
|
|
414
|
+
tokenManager.setTokens(response.accessToken, response.refreshToken);
|
|
415
|
+
}
|
|
416
|
+
return response;
|
|
417
|
+
}, [
|
|
418
|
+
authentication,
|
|
419
|
+
authMode,
|
|
420
|
+
tokenManager,
|
|
421
|
+
isAuthConfigured
|
|
422
|
+
]);
|
|
423
|
+
const signUp = useCallback(async (request)=>{
|
|
424
|
+
if (!isAuthConfigured) {
|
|
425
|
+
throw new Error('[23blocks] Cannot call signUp: The authentication service URL is not configured. ' + "Add 'urls.authentication' to your Provider configuration.");
|
|
426
|
+
}
|
|
427
|
+
const response = await authentication.auth.signUp(request);
|
|
428
|
+
if (authMode === 'token' && tokenManager && response.accessToken) {
|
|
429
|
+
tokenManager.setTokens(response.accessToken);
|
|
430
|
+
}
|
|
431
|
+
return response;
|
|
432
|
+
}, [
|
|
433
|
+
authentication,
|
|
434
|
+
authMode,
|
|
435
|
+
tokenManager,
|
|
436
|
+
isAuthConfigured
|
|
437
|
+
]);
|
|
438
|
+
const signOut = useCallback(async ()=>{
|
|
439
|
+
if (!isAuthConfigured) {
|
|
440
|
+
throw new Error('[23blocks] Cannot call signOut: The authentication service URL is not configured. ' + "Add 'urls.authentication' to your Provider configuration.");
|
|
441
|
+
}
|
|
442
|
+
await authentication.auth.signOut();
|
|
443
|
+
if (authMode === 'token' && tokenManager) {
|
|
444
|
+
tokenManager.clearTokens();
|
|
445
|
+
}
|
|
446
|
+
}, [
|
|
447
|
+
authentication,
|
|
448
|
+
authMode,
|
|
449
|
+
tokenManager,
|
|
450
|
+
isAuthConfigured
|
|
451
|
+
]);
|
|
452
|
+
// Token utilities
|
|
453
|
+
const getAccessToken = useCallback(()=>{
|
|
454
|
+
var _tokenManager_getAccessToken;
|
|
455
|
+
return (_tokenManager_getAccessToken = tokenManager == null ? void 0 : tokenManager.getAccessToken()) != null ? _tokenManager_getAccessToken : null;
|
|
456
|
+
}, [
|
|
457
|
+
tokenManager
|
|
458
|
+
]);
|
|
459
|
+
const getRefreshToken = useCallback(()=>{
|
|
460
|
+
var _tokenManager_getRefreshToken;
|
|
461
|
+
return (_tokenManager_getRefreshToken = tokenManager == null ? void 0 : tokenManager.getRefreshToken()) != null ? _tokenManager_getRefreshToken : null;
|
|
462
|
+
}, [
|
|
463
|
+
tokenManager
|
|
464
|
+
]);
|
|
465
|
+
const setTokens = useCallback((accessToken, refreshToken)=>{
|
|
466
|
+
tokenManager == null ? void 0 : tokenManager.setTokens(accessToken, refreshToken);
|
|
467
|
+
}, [
|
|
468
|
+
tokenManager
|
|
469
|
+
]);
|
|
470
|
+
const clearTokens = useCallback(()=>tokenManager == null ? void 0 : tokenManager.clearTokens(), [
|
|
471
|
+
tokenManager
|
|
472
|
+
]);
|
|
473
|
+
const isAuthenticated = useCallback(()=>{
|
|
474
|
+
if (authMode === 'cookie') return null;
|
|
475
|
+
return tokenManager ? !!tokenManager.getAccessToken() : false;
|
|
476
|
+
}, [
|
|
477
|
+
authMode,
|
|
478
|
+
tokenManager
|
|
479
|
+
]);
|
|
480
|
+
const onStorageChange = useCallback((callback)=>{
|
|
481
|
+
var _tokenManager_onStorageChange;
|
|
482
|
+
return (_tokenManager_onStorageChange = tokenManager == null ? void 0 : tokenManager.onStorageChange(callback)) != null ? _tokenManager_onStorageChange : ()=>{};
|
|
483
|
+
}, [
|
|
484
|
+
tokenManager
|
|
485
|
+
]);
|
|
486
|
+
const value = useMemo(()=>({
|
|
487
|
+
// Blocks
|
|
488
|
+
authentication,
|
|
489
|
+
search,
|
|
490
|
+
products,
|
|
491
|
+
crm,
|
|
492
|
+
content,
|
|
493
|
+
geolocation,
|
|
494
|
+
conversations,
|
|
495
|
+
files,
|
|
496
|
+
forms,
|
|
497
|
+
assets,
|
|
498
|
+
campaigns,
|
|
499
|
+
company,
|
|
500
|
+
rewards,
|
|
501
|
+
sales,
|
|
502
|
+
wallet,
|
|
503
|
+
jarvis,
|
|
504
|
+
onboarding,
|
|
505
|
+
university,
|
|
506
|
+
// Auth with token management
|
|
507
|
+
signIn,
|
|
508
|
+
signUp,
|
|
509
|
+
signOut,
|
|
510
|
+
// Token utilities
|
|
511
|
+
getAccessToken,
|
|
512
|
+
getRefreshToken,
|
|
513
|
+
setTokens,
|
|
514
|
+
clearTokens,
|
|
515
|
+
isAuthenticated,
|
|
516
|
+
onStorageChange,
|
|
517
|
+
// Config
|
|
518
|
+
authMode
|
|
519
|
+
}), [
|
|
520
|
+
authentication,
|
|
521
|
+
search,
|
|
522
|
+
products,
|
|
523
|
+
crm,
|
|
524
|
+
content,
|
|
525
|
+
geolocation,
|
|
526
|
+
conversations,
|
|
527
|
+
files,
|
|
528
|
+
forms,
|
|
529
|
+
assets,
|
|
530
|
+
campaigns,
|
|
531
|
+
company,
|
|
532
|
+
rewards,
|
|
533
|
+
sales,
|
|
534
|
+
wallet,
|
|
535
|
+
jarvis,
|
|
536
|
+
onboarding,
|
|
537
|
+
university,
|
|
538
|
+
signIn,
|
|
539
|
+
signUp,
|
|
540
|
+
signOut,
|
|
541
|
+
getAccessToken,
|
|
542
|
+
getRefreshToken,
|
|
543
|
+
setTokens,
|
|
544
|
+
clearTokens,
|
|
545
|
+
isAuthenticated,
|
|
546
|
+
onStorageChange,
|
|
547
|
+
authMode
|
|
548
|
+
]);
|
|
549
|
+
return jsx(Blocks23Context.Provider, {
|
|
550
|
+
value: value,
|
|
551
|
+
children: children
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
555
|
+
// Hooks
|
|
556
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
557
|
+
/**
|
|
558
|
+
* Hook to access all 23blocks services.
|
|
559
|
+
*
|
|
560
|
+
* @example
|
|
561
|
+
* ```tsx
|
|
562
|
+
* function Dashboard() {
|
|
563
|
+
* const { products, crm, files } = useClient();
|
|
564
|
+
*
|
|
565
|
+
* // Access any service
|
|
566
|
+
* const loadProducts = async () => {
|
|
567
|
+
* const { data } = await products.products.list({ limit: 10 });
|
|
568
|
+
* };
|
|
569
|
+
* }
|
|
570
|
+
* ```
|
|
571
|
+
*/ function useClient() {
|
|
572
|
+
const context = useContext(Blocks23Context);
|
|
573
|
+
if (!context) {
|
|
574
|
+
throw new Error('useClient must be used within a Provider');
|
|
575
|
+
}
|
|
576
|
+
return context;
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Hook for authentication operations with automatic token management.
|
|
580
|
+
*
|
|
581
|
+
* @example
|
|
582
|
+
* ```tsx
|
|
583
|
+
* function LoginPage() {
|
|
584
|
+
* const { signIn, signOut, isAuthenticated } = useAuth();
|
|
585
|
+
*
|
|
586
|
+
* const handleLogin = async () => {
|
|
587
|
+
* await signIn({ email: 'user@example.com', password: 'password' });
|
|
588
|
+
* };
|
|
589
|
+
*
|
|
590
|
+
* return (
|
|
591
|
+
* <div>
|
|
592
|
+
* {isAuthenticated() ? (
|
|
593
|
+
* <button onClick={signOut}>Sign Out</button>
|
|
594
|
+
* ) : (
|
|
595
|
+
* <button onClick={handleLogin}>Sign In</button>
|
|
596
|
+
* )}
|
|
597
|
+
* </div>
|
|
598
|
+
* );
|
|
599
|
+
* }
|
|
600
|
+
* ```
|
|
601
|
+
*/ function useAuth$1() {
|
|
602
|
+
const context = useClient();
|
|
603
|
+
return {
|
|
604
|
+
signIn: context.signIn,
|
|
605
|
+
signUp: context.signUp,
|
|
606
|
+
signOut: context.signOut,
|
|
607
|
+
getAccessToken: context.getAccessToken,
|
|
608
|
+
getRefreshToken: context.getRefreshToken,
|
|
609
|
+
setTokens: context.setTokens,
|
|
610
|
+
clearTokens: context.clearTokens,
|
|
611
|
+
isAuthenticated: context.isAuthenticated,
|
|
612
|
+
onStorageChange: context.onStorageChange,
|
|
613
|
+
authentication: context.authentication
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
617
|
+
// Backward Compatibility Aliases (deprecated)
|
|
618
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
619
|
+
/** @deprecated Use `Provider` instead */ const SimpleBlocks23Provider = Provider;
|
|
620
|
+
/** @deprecated Use `useClient` instead */ const useSimpleBlocks23 = useClient;
|
|
621
|
+
/** @deprecated Use `useAuth` instead */ const useSimpleAuth = useAuth$1;
|
|
622
|
+
|
|
623
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
624
|
+
// Context
|
|
625
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
626
|
+
const Blocks23ContextInternal = /*#__PURE__*/ createContext(null);
|
|
627
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
628
|
+
// Provider Component
|
|
629
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
630
|
+
/**
|
|
631
|
+
* Provider component for 23blocks services.
|
|
632
|
+
*
|
|
633
|
+
* @example
|
|
634
|
+
* ```tsx
|
|
635
|
+
* import { Blocks23Provider } from '@23blocks/react';
|
|
636
|
+
* import { createHttpTransport } from '@23blocks/transport-http';
|
|
637
|
+
*
|
|
638
|
+
* const transport = createHttpTransport({
|
|
639
|
+
* baseUrl: 'https://api.example.com',
|
|
640
|
+
* headers: () => ({
|
|
641
|
+
* 'Authorization': `Bearer ${localStorage.getItem('token')}`,
|
|
642
|
+
* }),
|
|
643
|
+
* });
|
|
644
|
+
*
|
|
645
|
+
* function App() {
|
|
646
|
+
* return (
|
|
647
|
+
* <Blocks23Provider
|
|
648
|
+
* transport={transport}
|
|
649
|
+
* authentication={{ appId: 'my-app' }}
|
|
650
|
+
* search={{ appId: 'my-app' }}
|
|
651
|
+
* products={{ appId: 'my-app' }}
|
|
652
|
+
* crm={{ appId: 'my-app' }}
|
|
653
|
+
* >
|
|
654
|
+
* <MyApp />
|
|
655
|
+
* </Blocks23Provider>
|
|
656
|
+
* );
|
|
657
|
+
* }
|
|
658
|
+
* ```
|
|
659
|
+
*/ function Blocks23Provider({ children, transport, authentication, search, products, crm, content, geolocation, conversations, files, forms, assets, campaigns, company, rewards, sales, wallet, jarvis, onboarding, university }) {
|
|
660
|
+
const value = useMemo(()=>({
|
|
661
|
+
transport,
|
|
662
|
+
authentication: authentication ? createAuthenticationBlock(transport, authentication) : null,
|
|
663
|
+
search: search ? createSearchBlock(transport, search) : null,
|
|
664
|
+
products: products ? createProductsBlock(transport, products) : null,
|
|
665
|
+
crm: crm ? createCrmBlock(transport, crm) : null,
|
|
666
|
+
content: content ? createContentBlock(transport, content) : null,
|
|
667
|
+
geolocation: geolocation ? createGeolocationBlock(transport, geolocation) : null,
|
|
668
|
+
conversations: conversations ? createConversationsBlock(transport, conversations) : null,
|
|
669
|
+
files: files ? createFilesBlock(transport, files) : null,
|
|
670
|
+
forms: forms ? createFormsBlock(transport, forms) : null,
|
|
671
|
+
assets: assets ? createAssetsBlock(transport, assets) : null,
|
|
672
|
+
campaigns: campaigns ? createCampaignsBlock(transport, campaigns) : null,
|
|
673
|
+
company: company ? createCompanyBlock(transport, company) : null,
|
|
674
|
+
rewards: rewards ? createRewardsBlock(transport, rewards) : null,
|
|
675
|
+
sales: sales ? createSalesBlock(transport, sales) : null,
|
|
676
|
+
wallet: wallet ? createWalletBlock(transport, wallet) : null,
|
|
677
|
+
jarvis: jarvis ? createJarvisBlock(transport, jarvis) : null,
|
|
678
|
+
onboarding: onboarding ? createOnboardingBlock(transport, onboarding) : null,
|
|
679
|
+
university: university ? createUniversityBlock(transport, university) : null
|
|
680
|
+
}), [
|
|
681
|
+
transport,
|
|
682
|
+
authentication,
|
|
683
|
+
search,
|
|
684
|
+
products,
|
|
685
|
+
crm,
|
|
686
|
+
content,
|
|
687
|
+
geolocation,
|
|
688
|
+
conversations,
|
|
689
|
+
files,
|
|
690
|
+
forms,
|
|
691
|
+
assets,
|
|
692
|
+
campaigns,
|
|
693
|
+
company,
|
|
694
|
+
rewards,
|
|
695
|
+
sales,
|
|
696
|
+
wallet,
|
|
697
|
+
jarvis,
|
|
698
|
+
onboarding,
|
|
699
|
+
university
|
|
700
|
+
]);
|
|
701
|
+
return jsx(Blocks23ContextInternal.Provider, {
|
|
702
|
+
value: value,
|
|
703
|
+
children: children
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
707
|
+
// Context Hook
|
|
708
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
709
|
+
function use23Blocks() {
|
|
710
|
+
const context = useContext(Blocks23ContextInternal);
|
|
711
|
+
if (!context) {
|
|
712
|
+
throw new Error('use23Blocks must be used within a Blocks23Provider');
|
|
713
|
+
}
|
|
714
|
+
return context;
|
|
715
|
+
}
|
|
716
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
717
|
+
// Block-specific hooks
|
|
718
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
719
|
+
function useAuthenticationBlock() {
|
|
720
|
+
const { authentication } = use23Blocks();
|
|
721
|
+
if (!authentication) throw new Error('Authentication block not configured. Pass `authentication` prop to Blocks23Provider.');
|
|
722
|
+
return authentication;
|
|
723
|
+
}
|
|
724
|
+
function useSearchBlock() {
|
|
725
|
+
const { search } = use23Blocks();
|
|
726
|
+
if (!search) throw new Error('Search block not configured. Pass `search` prop to Blocks23Provider.');
|
|
727
|
+
return search;
|
|
728
|
+
}
|
|
729
|
+
function useProductsBlock() {
|
|
730
|
+
const { products } = use23Blocks();
|
|
731
|
+
if (!products) throw new Error('Products block not configured. Pass `products` prop to Blocks23Provider.');
|
|
732
|
+
return products;
|
|
733
|
+
}
|
|
734
|
+
function useCrmBlock() {
|
|
735
|
+
const { crm } = use23Blocks();
|
|
736
|
+
if (!crm) throw new Error('CRM block not configured. Pass `crm` prop to Blocks23Provider.');
|
|
737
|
+
return crm;
|
|
738
|
+
}
|
|
739
|
+
function useContentBlock() {
|
|
740
|
+
const { content } = use23Blocks();
|
|
741
|
+
if (!content) throw new Error('Content block not configured. Pass `content` prop to Blocks23Provider.');
|
|
742
|
+
return content;
|
|
743
|
+
}
|
|
744
|
+
function useGeolocationBlock() {
|
|
745
|
+
const { geolocation } = use23Blocks();
|
|
746
|
+
if (!geolocation) throw new Error('Geolocation block not configured. Pass `geolocation` prop to Blocks23Provider.');
|
|
747
|
+
return geolocation;
|
|
748
|
+
}
|
|
749
|
+
function useConversationsBlock() {
|
|
750
|
+
const { conversations } = use23Blocks();
|
|
751
|
+
if (!conversations) throw new Error('Conversations block not configured. Pass `conversations` prop to Blocks23Provider.');
|
|
752
|
+
return conversations;
|
|
753
|
+
}
|
|
754
|
+
function useFilesBlock() {
|
|
755
|
+
const { files } = use23Blocks();
|
|
756
|
+
if (!files) throw new Error('Files block not configured. Pass `files` prop to Blocks23Provider.');
|
|
757
|
+
return files;
|
|
758
|
+
}
|
|
759
|
+
function useFormsBlock() {
|
|
760
|
+
const { forms } = use23Blocks();
|
|
761
|
+
if (!forms) throw new Error('Forms block not configured. Pass `forms` prop to Blocks23Provider.');
|
|
762
|
+
return forms;
|
|
763
|
+
}
|
|
764
|
+
function useAssetsBlock() {
|
|
765
|
+
const { assets } = use23Blocks();
|
|
766
|
+
if (!assets) throw new Error('Assets block not configured. Pass `assets` prop to Blocks23Provider.');
|
|
767
|
+
return assets;
|
|
768
|
+
}
|
|
769
|
+
function useCampaignsBlock() {
|
|
770
|
+
const { campaigns } = use23Blocks();
|
|
771
|
+
if (!campaigns) throw new Error('Campaigns block not configured. Pass `campaigns` prop to Blocks23Provider.');
|
|
772
|
+
return campaigns;
|
|
773
|
+
}
|
|
774
|
+
function useCompanyBlock() {
|
|
775
|
+
const { company } = use23Blocks();
|
|
776
|
+
if (!company) throw new Error('Company block not configured. Pass `company` prop to Blocks23Provider.');
|
|
777
|
+
return company;
|
|
778
|
+
}
|
|
779
|
+
function useRewardsBlock() {
|
|
780
|
+
const { rewards } = use23Blocks();
|
|
781
|
+
if (!rewards) throw new Error('Rewards block not configured. Pass `rewards` prop to Blocks23Provider.');
|
|
782
|
+
return rewards;
|
|
783
|
+
}
|
|
784
|
+
function useSalesBlock() {
|
|
785
|
+
const { sales } = use23Blocks();
|
|
786
|
+
if (!sales) throw new Error('Sales block not configured. Pass `sales` prop to Blocks23Provider.');
|
|
787
|
+
return sales;
|
|
788
|
+
}
|
|
789
|
+
function useWalletBlock() {
|
|
790
|
+
const { wallet } = use23Blocks();
|
|
791
|
+
if (!wallet) throw new Error('Wallet block not configured. Pass `wallet` prop to Blocks23Provider.');
|
|
792
|
+
return wallet;
|
|
793
|
+
}
|
|
794
|
+
function useJarvisBlock() {
|
|
795
|
+
const { jarvis } = use23Blocks();
|
|
796
|
+
if (!jarvis) throw new Error('Jarvis block not configured. Pass `jarvis` prop to Blocks23Provider.');
|
|
797
|
+
return jarvis;
|
|
798
|
+
}
|
|
799
|
+
function useOnboardingBlock() {
|
|
800
|
+
const { onboarding } = use23Blocks();
|
|
801
|
+
if (!onboarding) throw new Error('Onboarding block not configured. Pass `onboarding` prop to Blocks23Provider.');
|
|
802
|
+
return onboarding;
|
|
803
|
+
}
|
|
804
|
+
function useUniversityBlock() {
|
|
805
|
+
const { university } = use23Blocks();
|
|
806
|
+
if (!university) throw new Error('University block not configured. Pass `university` prop to Blocks23Provider.');
|
|
807
|
+
return university;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
811
|
+
// Hook
|
|
812
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
813
|
+
/**
|
|
814
|
+
* Hook for authentication operations with state management.
|
|
815
|
+
*
|
|
816
|
+
* @example
|
|
817
|
+
* ```tsx
|
|
818
|
+
* function LoginForm() {
|
|
819
|
+
* const { signIn, isLoading, error, user } = useAuth();
|
|
820
|
+
*
|
|
821
|
+
* const handleSubmit = async (e: FormEvent) => {
|
|
822
|
+
* e.preventDefault();
|
|
823
|
+
* try {
|
|
824
|
+
* await signIn({ email, password });
|
|
825
|
+
* navigate('/dashboard');
|
|
826
|
+
* } catch (err) {
|
|
827
|
+
* // Error is automatically captured in `error` state
|
|
828
|
+
* }
|
|
829
|
+
* };
|
|
830
|
+
*
|
|
831
|
+
* if (user) {
|
|
832
|
+
* return <p>Welcome, {user.email}!</p>;
|
|
833
|
+
* }
|
|
834
|
+
*
|
|
835
|
+
* return (
|
|
836
|
+
* <form onSubmit={handleSubmit}>
|
|
837
|
+
* {error && <p className="error">{error.message}</p>}
|
|
838
|
+
* <button disabled={isLoading}>
|
|
839
|
+
* {isLoading ? 'Signing in...' : 'Sign In'}
|
|
840
|
+
* </button>
|
|
841
|
+
* </form>
|
|
842
|
+
* );
|
|
843
|
+
* }
|
|
844
|
+
* ```
|
|
845
|
+
*/ function useAuth() {
|
|
846
|
+
const block = useAuthenticationBlock();
|
|
847
|
+
const [user, setUser] = useState(null);
|
|
848
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
849
|
+
const [error, setError] = useState(null);
|
|
850
|
+
const signIn = useCallback(async (request)=>{
|
|
851
|
+
setIsLoading(true);
|
|
852
|
+
setError(null);
|
|
853
|
+
try {
|
|
854
|
+
const response = await block.auth.signIn(request);
|
|
855
|
+
setUser(response.user);
|
|
856
|
+
return response;
|
|
857
|
+
} catch (err) {
|
|
858
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
859
|
+
setError(error);
|
|
860
|
+
throw error;
|
|
861
|
+
} finally{
|
|
862
|
+
setIsLoading(false);
|
|
863
|
+
}
|
|
864
|
+
}, [
|
|
865
|
+
block.auth
|
|
866
|
+
]);
|
|
867
|
+
const signUp = useCallback(async (request)=>{
|
|
868
|
+
setIsLoading(true);
|
|
869
|
+
setError(null);
|
|
870
|
+
try {
|
|
871
|
+
const response = await block.auth.signUp(request);
|
|
872
|
+
setUser(response.user);
|
|
873
|
+
return response;
|
|
874
|
+
} catch (err) {
|
|
875
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
876
|
+
setError(error);
|
|
877
|
+
throw error;
|
|
878
|
+
} finally{
|
|
879
|
+
setIsLoading(false);
|
|
880
|
+
}
|
|
881
|
+
}, [
|
|
882
|
+
block.auth
|
|
883
|
+
]);
|
|
884
|
+
const signOut = useCallback(async ()=>{
|
|
885
|
+
setIsLoading(true);
|
|
886
|
+
setError(null);
|
|
887
|
+
try {
|
|
888
|
+
await block.auth.signOut();
|
|
889
|
+
setUser(null);
|
|
890
|
+
} catch (err) {
|
|
891
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
892
|
+
setError(error);
|
|
893
|
+
throw error;
|
|
894
|
+
} finally{
|
|
895
|
+
setIsLoading(false);
|
|
896
|
+
}
|
|
897
|
+
}, [
|
|
898
|
+
block.auth
|
|
899
|
+
]);
|
|
900
|
+
const requestPasswordReset = useCallback(async (request)=>{
|
|
901
|
+
setIsLoading(true);
|
|
902
|
+
setError(null);
|
|
903
|
+
try {
|
|
904
|
+
await block.auth.requestPasswordReset(request);
|
|
905
|
+
} catch (err) {
|
|
906
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
907
|
+
setError(error);
|
|
908
|
+
throw error;
|
|
909
|
+
} finally{
|
|
910
|
+
setIsLoading(false);
|
|
911
|
+
}
|
|
912
|
+
}, [
|
|
913
|
+
block.auth
|
|
914
|
+
]);
|
|
915
|
+
const updatePassword = useCallback(async (request)=>{
|
|
916
|
+
setIsLoading(true);
|
|
917
|
+
setError(null);
|
|
918
|
+
try {
|
|
919
|
+
await block.auth.updatePassword(request);
|
|
920
|
+
} catch (err) {
|
|
921
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
922
|
+
setError(error);
|
|
923
|
+
throw error;
|
|
924
|
+
} finally{
|
|
925
|
+
setIsLoading(false);
|
|
926
|
+
}
|
|
927
|
+
}, [
|
|
928
|
+
block.auth
|
|
929
|
+
]);
|
|
930
|
+
const refreshUser = useCallback(async ()=>{
|
|
931
|
+
setIsLoading(true);
|
|
932
|
+
setError(null);
|
|
933
|
+
try {
|
|
934
|
+
const currentUser = await block.auth.getCurrentUser();
|
|
935
|
+
setUser(currentUser);
|
|
936
|
+
} catch (err) {
|
|
937
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
938
|
+
setError(error);
|
|
939
|
+
throw error;
|
|
940
|
+
} finally{
|
|
941
|
+
setIsLoading(false);
|
|
942
|
+
}
|
|
943
|
+
}, [
|
|
944
|
+
block.auth
|
|
945
|
+
]);
|
|
946
|
+
const clearError = useCallback(()=>{
|
|
947
|
+
setError(null);
|
|
948
|
+
}, []);
|
|
949
|
+
return {
|
|
950
|
+
// State
|
|
951
|
+
user,
|
|
952
|
+
isLoading,
|
|
953
|
+
error,
|
|
954
|
+
isAuthenticated: user !== null,
|
|
955
|
+
// Actions
|
|
956
|
+
signIn,
|
|
957
|
+
signUp,
|
|
958
|
+
signOut,
|
|
959
|
+
requestPasswordReset,
|
|
960
|
+
updatePassword,
|
|
961
|
+
refreshUser,
|
|
962
|
+
clearError
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
967
|
+
// Hook
|
|
968
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
969
|
+
/**
|
|
970
|
+
* Hook for user management operations.
|
|
971
|
+
*
|
|
972
|
+
* @example
|
|
973
|
+
* ```tsx
|
|
974
|
+
* function UserList() {
|
|
975
|
+
* const { users, listUsers, isLoading, error } = useUsers();
|
|
976
|
+
*
|
|
977
|
+
* useEffect(() => {
|
|
978
|
+
* listUsers({ page: 1, perPage: 20 });
|
|
979
|
+
* }, [listUsers]);
|
|
980
|
+
*
|
|
981
|
+
* if (isLoading) return <Spinner />;
|
|
982
|
+
* if (error) return <Error message={error.message} />;
|
|
983
|
+
*
|
|
984
|
+
* return (
|
|
985
|
+
* <ul>
|
|
986
|
+
* {users.map(user => (
|
|
987
|
+
* <li key={user.id}>{user.email}</li>
|
|
988
|
+
* ))}
|
|
989
|
+
* </ul>
|
|
990
|
+
* );
|
|
991
|
+
* }
|
|
992
|
+
* ```
|
|
993
|
+
*/ function useUsers() {
|
|
994
|
+
const block = useAuthenticationBlock();
|
|
995
|
+
const [users, setUsers] = useState([]);
|
|
996
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
997
|
+
const [error, setError] = useState(null);
|
|
998
|
+
const listUsers = useCallback(async (params)=>{
|
|
999
|
+
setIsLoading(true);
|
|
1000
|
+
setError(null);
|
|
1001
|
+
try {
|
|
1002
|
+
const result = await block.users.list(params);
|
|
1003
|
+
setUsers(result);
|
|
1004
|
+
return result;
|
|
1005
|
+
} catch (err) {
|
|
1006
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1007
|
+
setError(error);
|
|
1008
|
+
throw error;
|
|
1009
|
+
} finally{
|
|
1010
|
+
setIsLoading(false);
|
|
1011
|
+
}
|
|
1012
|
+
}, [
|
|
1013
|
+
block.users
|
|
1014
|
+
]);
|
|
1015
|
+
const getUser = useCallback(async (id)=>{
|
|
1016
|
+
setIsLoading(true);
|
|
1017
|
+
setError(null);
|
|
1018
|
+
try {
|
|
1019
|
+
return await block.users.get(id);
|
|
1020
|
+
} catch (err) {
|
|
1021
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1022
|
+
setError(error);
|
|
1023
|
+
throw error;
|
|
1024
|
+
} finally{
|
|
1025
|
+
setIsLoading(false);
|
|
1026
|
+
}
|
|
1027
|
+
}, [
|
|
1028
|
+
block.users
|
|
1029
|
+
]);
|
|
1030
|
+
const updateUser = useCallback(async (id, request)=>{
|
|
1031
|
+
setIsLoading(true);
|
|
1032
|
+
setError(null);
|
|
1033
|
+
try {
|
|
1034
|
+
const updated = await block.users.update(id, request);
|
|
1035
|
+
setUsers((prev)=>prev.map((u)=>u.id === id ? updated : u));
|
|
1036
|
+
return updated;
|
|
1037
|
+
} catch (err) {
|
|
1038
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1039
|
+
setError(error);
|
|
1040
|
+
throw error;
|
|
1041
|
+
} finally{
|
|
1042
|
+
setIsLoading(false);
|
|
1043
|
+
}
|
|
1044
|
+
}, [
|
|
1045
|
+
block.users
|
|
1046
|
+
]);
|
|
1047
|
+
const deleteUser = useCallback(async (id)=>{
|
|
1048
|
+
setIsLoading(true);
|
|
1049
|
+
setError(null);
|
|
1050
|
+
try {
|
|
1051
|
+
await block.users.delete(id);
|
|
1052
|
+
setUsers((prev)=>prev.filter((u)=>u.id !== id));
|
|
1053
|
+
} catch (err) {
|
|
1054
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1055
|
+
setError(error);
|
|
1056
|
+
throw error;
|
|
1057
|
+
} finally{
|
|
1058
|
+
setIsLoading(false);
|
|
1059
|
+
}
|
|
1060
|
+
}, [
|
|
1061
|
+
block.users
|
|
1062
|
+
]);
|
|
1063
|
+
const clearError = useCallback(()=>{
|
|
1064
|
+
setError(null);
|
|
1065
|
+
}, []);
|
|
1066
|
+
return {
|
|
1067
|
+
users,
|
|
1068
|
+
isLoading,
|
|
1069
|
+
error,
|
|
1070
|
+
listUsers,
|
|
1071
|
+
getUser,
|
|
1072
|
+
updateUser,
|
|
1073
|
+
deleteUser,
|
|
1074
|
+
clearError
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1079
|
+
// Hook
|
|
1080
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1081
|
+
/**
|
|
1082
|
+
* Hook for search operations with state management.
|
|
1083
|
+
*
|
|
1084
|
+
* @example
|
|
1085
|
+
* ```tsx
|
|
1086
|
+
* function SearchPage() {
|
|
1087
|
+
* const { results, search, isLoading, query } = useSearch();
|
|
1088
|
+
* const [inputValue, setInputValue] = useState('');
|
|
1089
|
+
*
|
|
1090
|
+
* const handleSearch = async (e: FormEvent) => {
|
|
1091
|
+
* e.preventDefault();
|
|
1092
|
+
* await search({ query: inputValue });
|
|
1093
|
+
* };
|
|
1094
|
+
*
|
|
1095
|
+
* return (
|
|
1096
|
+
* <div>
|
|
1097
|
+
* <form onSubmit={handleSearch}>
|
|
1098
|
+
* <input
|
|
1099
|
+
* value={inputValue}
|
|
1100
|
+
* onChange={(e) => setInputValue(e.target.value)}
|
|
1101
|
+
* placeholder="Search..."
|
|
1102
|
+
* />
|
|
1103
|
+
* <button disabled={isLoading}>Search</button>
|
|
1104
|
+
* </form>
|
|
1105
|
+
*
|
|
1106
|
+
* {query && <p>Results for: {query}</p>}
|
|
1107
|
+
*
|
|
1108
|
+
* <ul>
|
|
1109
|
+
* {results.map(result => (
|
|
1110
|
+
* <li key={result.id}>{result.entityDescription}</li>
|
|
1111
|
+
* ))}
|
|
1112
|
+
* </ul>
|
|
1113
|
+
* </div>
|
|
1114
|
+
* );
|
|
1115
|
+
* }
|
|
1116
|
+
* ```
|
|
1117
|
+
*/ function useSearch() {
|
|
1118
|
+
const block = useSearchBlock();
|
|
1119
|
+
const [results, setResults] = useState([]);
|
|
1120
|
+
const [totalRecords, setTotalRecords] = useState(0);
|
|
1121
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
1122
|
+
const [error, setError] = useState(null);
|
|
1123
|
+
const [query, setQuery] = useState('');
|
|
1124
|
+
const search = useCallback(async (request)=>{
|
|
1125
|
+
setIsLoading(true);
|
|
1126
|
+
setError(null);
|
|
1127
|
+
setQuery(request.query);
|
|
1128
|
+
try {
|
|
1129
|
+
const response = await block.search.search(request);
|
|
1130
|
+
setResults(response.results);
|
|
1131
|
+
setTotalRecords(response.totalRecords);
|
|
1132
|
+
return response;
|
|
1133
|
+
} catch (err) {
|
|
1134
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1135
|
+
setError(error);
|
|
1136
|
+
throw error;
|
|
1137
|
+
} finally{
|
|
1138
|
+
setIsLoading(false);
|
|
1139
|
+
}
|
|
1140
|
+
}, [
|
|
1141
|
+
block.search
|
|
1142
|
+
]);
|
|
1143
|
+
const suggest = useCallback(async (query, limit)=>{
|
|
1144
|
+
setIsLoading(true);
|
|
1145
|
+
setError(null);
|
|
1146
|
+
try {
|
|
1147
|
+
return await block.search.suggest(query, limit);
|
|
1148
|
+
} catch (err) {
|
|
1149
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1150
|
+
setError(error);
|
|
1151
|
+
throw error;
|
|
1152
|
+
} finally{
|
|
1153
|
+
setIsLoading(false);
|
|
1154
|
+
}
|
|
1155
|
+
}, [
|
|
1156
|
+
block.search
|
|
1157
|
+
]);
|
|
1158
|
+
const getEntityTypes = useCallback(async ()=>{
|
|
1159
|
+
setIsLoading(true);
|
|
1160
|
+
setError(null);
|
|
1161
|
+
try {
|
|
1162
|
+
return await block.search.entityTypes();
|
|
1163
|
+
} catch (err) {
|
|
1164
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1165
|
+
setError(error);
|
|
1166
|
+
throw error;
|
|
1167
|
+
} finally{
|
|
1168
|
+
setIsLoading(false);
|
|
1169
|
+
}
|
|
1170
|
+
}, [
|
|
1171
|
+
block.search
|
|
1172
|
+
]);
|
|
1173
|
+
const clearResults = useCallback(()=>{
|
|
1174
|
+
setResults([]);
|
|
1175
|
+
setTotalRecords(0);
|
|
1176
|
+
setQuery('');
|
|
1177
|
+
}, []);
|
|
1178
|
+
const clearError = useCallback(()=>{
|
|
1179
|
+
setError(null);
|
|
1180
|
+
}, []);
|
|
1181
|
+
return {
|
|
1182
|
+
results,
|
|
1183
|
+
totalRecords,
|
|
1184
|
+
isLoading,
|
|
1185
|
+
error,
|
|
1186
|
+
query,
|
|
1187
|
+
search,
|
|
1188
|
+
suggest,
|
|
1189
|
+
getEntityTypes,
|
|
1190
|
+
clearResults,
|
|
1191
|
+
clearError
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1196
|
+
// Hook
|
|
1197
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
1198
|
+
/**
|
|
1199
|
+
* Hook for managing favorites.
|
|
1200
|
+
*
|
|
1201
|
+
* @example
|
|
1202
|
+
* ```tsx
|
|
1203
|
+
* function FavoritesList() {
|
|
1204
|
+
* const { favorites, listFavorites, removeFavorite, isLoading } = useFavorites();
|
|
1205
|
+
*
|
|
1206
|
+
* useEffect(() => {
|
|
1207
|
+
* listFavorites();
|
|
1208
|
+
* }, [listFavorites]);
|
|
1209
|
+
*
|
|
1210
|
+
* return (
|
|
1211
|
+
* <ul>
|
|
1212
|
+
* {favorites.map(fav => (
|
|
1213
|
+
* <li key={fav.id}>
|
|
1214
|
+
* {fav.entityDescription}
|
|
1215
|
+
* <button onClick={() => removeFavorite(fav.id)}>Remove</button>
|
|
1216
|
+
* </li>
|
|
1217
|
+
* ))}
|
|
1218
|
+
* </ul>
|
|
1219
|
+
* );
|
|
1220
|
+
* }
|
|
1221
|
+
* ```
|
|
1222
|
+
*/ function useFavorites() {
|
|
1223
|
+
const block = useSearchBlock();
|
|
1224
|
+
const [favorites, setFavorites] = useState([]);
|
|
1225
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
1226
|
+
const [error, setError] = useState(null);
|
|
1227
|
+
const listFavorites = useCallback(async ()=>{
|
|
1228
|
+
setIsLoading(true);
|
|
1229
|
+
setError(null);
|
|
1230
|
+
try {
|
|
1231
|
+
const result = await block.favorites.list();
|
|
1232
|
+
setFavorites(result);
|
|
1233
|
+
return result;
|
|
1234
|
+
} catch (err) {
|
|
1235
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1236
|
+
setError(error);
|
|
1237
|
+
throw error;
|
|
1238
|
+
} finally{
|
|
1239
|
+
setIsLoading(false);
|
|
1240
|
+
}
|
|
1241
|
+
}, [
|
|
1242
|
+
block.favorites
|
|
1243
|
+
]);
|
|
1244
|
+
const addFavorite = useCallback(async (request)=>{
|
|
1245
|
+
setIsLoading(true);
|
|
1246
|
+
setError(null);
|
|
1247
|
+
try {
|
|
1248
|
+
const favorite = await block.favorites.add(request);
|
|
1249
|
+
setFavorites((prev)=>[
|
|
1250
|
+
...prev,
|
|
1251
|
+
favorite
|
|
1252
|
+
]);
|
|
1253
|
+
return favorite;
|
|
1254
|
+
} catch (err) {
|
|
1255
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1256
|
+
setError(error);
|
|
1257
|
+
throw error;
|
|
1258
|
+
} finally{
|
|
1259
|
+
setIsLoading(false);
|
|
1260
|
+
}
|
|
1261
|
+
}, [
|
|
1262
|
+
block.favorites
|
|
1263
|
+
]);
|
|
1264
|
+
const removeFavorite = useCallback(async (id)=>{
|
|
1265
|
+
setIsLoading(true);
|
|
1266
|
+
setError(null);
|
|
1267
|
+
try {
|
|
1268
|
+
await block.favorites.remove(id);
|
|
1269
|
+
setFavorites((prev)=>prev.filter((f)=>f.id !== id));
|
|
1270
|
+
} catch (err) {
|
|
1271
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1272
|
+
setError(error);
|
|
1273
|
+
throw error;
|
|
1274
|
+
} finally{
|
|
1275
|
+
setIsLoading(false);
|
|
1276
|
+
}
|
|
1277
|
+
}, [
|
|
1278
|
+
block.favorites
|
|
1279
|
+
]);
|
|
1280
|
+
const isFavorite = useCallback(async (entityUniqueId)=>{
|
|
1281
|
+
try {
|
|
1282
|
+
return await block.favorites.isFavorite(entityUniqueId);
|
|
1283
|
+
} catch (err) {
|
|
1284
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1285
|
+
setError(error);
|
|
1286
|
+
throw error;
|
|
1287
|
+
}
|
|
1288
|
+
}, [
|
|
1289
|
+
block.favorites
|
|
1290
|
+
]);
|
|
1291
|
+
const clearError = useCallback(()=>{
|
|
1292
|
+
setError(null);
|
|
1293
|
+
}, []);
|
|
1294
|
+
return {
|
|
1295
|
+
favorites,
|
|
1296
|
+
isLoading,
|
|
1297
|
+
error,
|
|
1298
|
+
listFavorites,
|
|
1299
|
+
addFavorite,
|
|
1300
|
+
removeFavorite,
|
|
1301
|
+
isFavorite,
|
|
1302
|
+
clearError
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
export { Blocks23Provider, Provider, SimpleBlocks23Provider, use23Blocks, useAssetsBlock, useAuth$1 as useAuth, useAuth as useAuthState, useAuthenticationBlock, useCampaignsBlock, useClient, useCompanyBlock, useContentBlock, useConversationsBlock, useCrmBlock, useFavorites, useFilesBlock, useFormsBlock, useGeolocationBlock, useJarvisBlock, useOnboardingBlock, useProductsBlock, useRewardsBlock, useSalesBlock, useSearch, useSearchBlock, useSimpleAuth, useSimpleBlocks23, useUniversityBlock, useUsers, useWalletBlock };
|