@basictech/react 0.5.0-beta.3 → 0.5.0-beta.5
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/changelog.md +12 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +117 -74
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +117 -74
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/AuthContext.tsx +140 -104
package/src/AuthContext.tsx
CHANGED
|
@@ -8,13 +8,7 @@ import { get, add, update, deleteRecord } from './db'
|
|
|
8
8
|
import { validateSchema, compareSchemas } from '@basictech/schema'
|
|
9
9
|
|
|
10
10
|
import { log } from './config'
|
|
11
|
-
|
|
12
|
-
/*
|
|
13
|
-
schema todo:
|
|
14
|
-
field types
|
|
15
|
-
array types
|
|
16
|
-
relations
|
|
17
|
-
*/
|
|
11
|
+
import {version as currentVersion} from '../package.json'
|
|
18
12
|
|
|
19
13
|
type BasicSyncType = {
|
|
20
14
|
basic_schema: any;
|
|
@@ -192,9 +186,42 @@ type ErrorObject = {
|
|
|
192
186
|
message: string;
|
|
193
187
|
}
|
|
194
188
|
|
|
189
|
+
async function checkForNewVersion(): Promise<{ hasNewVersion: boolean, latestVersion: string | null, currentVersion: string | null }> {
|
|
190
|
+
try {
|
|
191
|
+
|
|
192
|
+
const isBeta = currentVersion.includes('beta')
|
|
193
|
+
|
|
194
|
+
const response = await fetch(`https://registry.npmjs.org/@basictech/react/${isBeta ? 'beta' : 'latest'}`);
|
|
195
|
+
if (!response.ok) {
|
|
196
|
+
throw new Error('Failed to fetch version from npm');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const data = await response.json();
|
|
200
|
+
const latestVersion = data.version;
|
|
195
201
|
|
|
202
|
+
if (latestVersion !== currentVersion) {
|
|
203
|
+
console.warn('[basic] New version available:', latestVersion, `\nrun "npm install @basictech/react@${latestVersion}" to update`);
|
|
204
|
+
}
|
|
205
|
+
if (isBeta) {
|
|
206
|
+
log('thank you for being on basictech/react beta :)')
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
hasNewVersion: currentVersion !== latestVersion,
|
|
211
|
+
latestVersion,
|
|
212
|
+
currentVersion
|
|
213
|
+
};
|
|
214
|
+
} catch (error) {
|
|
215
|
+
log('Error checking for new version:', error);
|
|
216
|
+
return {
|
|
217
|
+
hasNewVersion: false,
|
|
218
|
+
latestVersion: null,
|
|
219
|
+
currentVersion: null
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
196
223
|
|
|
197
|
-
export function BasicProvider({ children, project_id, schema, debug = false }: { children: React.ReactNode, project_id
|
|
224
|
+
export function BasicProvider({ children, project_id, schema, debug = false }: { children: React.ReactNode, project_id?: string, schema?: any, debug?: boolean }) {
|
|
198
225
|
const [isAuthReady, setIsAuthReady] = useState(false)
|
|
199
226
|
const [isSignedIn, setIsSignedIn] = useState<boolean>(false)
|
|
200
227
|
const [token, setToken] = useState<Token | null>(null)
|
|
@@ -208,7 +235,7 @@ export function BasicProvider({ children, project_id, schema, debug = false }: {
|
|
|
208
235
|
const syncRef = useRef<BasicSync | null>(null);
|
|
209
236
|
|
|
210
237
|
useEffect(() => {
|
|
211
|
-
function initDb() {
|
|
238
|
+
function initDb(options: { shouldConnect: boolean }) {
|
|
212
239
|
if (!syncRef.current) {
|
|
213
240
|
log('Initializing BasicDB')
|
|
214
241
|
syncRef.current = new BasicSync('basicdb', { schema: schema });
|
|
@@ -221,8 +248,12 @@ export function BasicProvider({ children, project_id, schema, debug = false }: {
|
|
|
221
248
|
setDbStatus(getSyncStatus(status))
|
|
222
249
|
})
|
|
223
250
|
|
|
251
|
+
if (options.shouldConnect) {
|
|
252
|
+
setShouldConnect(true)
|
|
253
|
+
} else {
|
|
254
|
+
log('Sync is disabled')
|
|
255
|
+
}
|
|
224
256
|
|
|
225
|
-
setShouldConnect(true)
|
|
226
257
|
setIsReady(true)
|
|
227
258
|
|
|
228
259
|
// log('db is open', syncRef.current.isOpen())
|
|
@@ -254,13 +285,18 @@ export function BasicProvider({ children, project_id, schema, debug = false }: {
|
|
|
254
285
|
}
|
|
255
286
|
|
|
256
287
|
|
|
257
|
-
|
|
288
|
+
let schemaStatus = { valid: false }
|
|
289
|
+
if (schema.version !== 0) {
|
|
290
|
+
schemaStatus = await getSchemaStatus(schema)
|
|
291
|
+
}
|
|
258
292
|
|
|
259
293
|
if (schemaStatus.valid) {
|
|
260
|
-
initDb()
|
|
294
|
+
initDb({ shouldConnect: true })
|
|
261
295
|
} else {
|
|
262
|
-
|
|
296
|
+
initDb({ shouldConnect: false })
|
|
263
297
|
}
|
|
298
|
+
|
|
299
|
+
checkForNewVersion()
|
|
264
300
|
}
|
|
265
301
|
|
|
266
302
|
if (schema) {
|
|
@@ -277,6 +313,97 @@ export function BasicProvider({ children, project_id, schema, debug = false }: {
|
|
|
277
313
|
}
|
|
278
314
|
}, [isSignedIn, shouldConnect])
|
|
279
315
|
|
|
316
|
+
useEffect(() => {
|
|
317
|
+
localStorage.setItem('basic_debug', debug ? 'true' : 'false')
|
|
318
|
+
|
|
319
|
+
try {
|
|
320
|
+
if (window.location.search.includes('code')) {
|
|
321
|
+
let code = window.location?.search?.split('code=')[1].split('&')[0]
|
|
322
|
+
|
|
323
|
+
const state = localStorage.getItem('basic_auth_state')
|
|
324
|
+
if (!state || state !== window.location.search.split('state=')[1].split('&')[0]) {
|
|
325
|
+
log('error: auth state does not match')
|
|
326
|
+
setIsAuthReady(true)
|
|
327
|
+
|
|
328
|
+
localStorage.removeItem('basic_auth_state')
|
|
329
|
+
window.history.pushState({}, document.title, "/");
|
|
330
|
+
return
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
localStorage.removeItem('basic_auth_state')
|
|
334
|
+
|
|
335
|
+
fetchToken(code)
|
|
336
|
+
} else {
|
|
337
|
+
let cookie_token = getCookie('basic_token')
|
|
338
|
+
if (cookie_token !== '') {
|
|
339
|
+
setToken(JSON.parse(cookie_token))
|
|
340
|
+
} else {
|
|
341
|
+
setIsAuthReady(true)
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
} catch (e) {
|
|
347
|
+
log('error getting cookie', e)
|
|
348
|
+
}
|
|
349
|
+
}, [])
|
|
350
|
+
|
|
351
|
+
useEffect(() => {
|
|
352
|
+
async function fetchUser(acc_token: string) {
|
|
353
|
+
console.info('fetching user')
|
|
354
|
+
const user = await fetch('https://api.basic.tech/auth/userInfo', {
|
|
355
|
+
method: 'GET',
|
|
356
|
+
headers: {
|
|
357
|
+
'Authorization': `Bearer ${acc_token}`
|
|
358
|
+
}
|
|
359
|
+
})
|
|
360
|
+
.then(response => response.json())
|
|
361
|
+
.catch(error => log('Error:', error))
|
|
362
|
+
|
|
363
|
+
if (user.error) {
|
|
364
|
+
log('error fetching user', user.error)
|
|
365
|
+
// refreshToken()
|
|
366
|
+
return
|
|
367
|
+
} else {
|
|
368
|
+
// log('user', user)
|
|
369
|
+
document.cookie = `basic_token=${JSON.stringify(token)}; Secure; SameSite=Strict`;
|
|
370
|
+
|
|
371
|
+
if (window.location.search.includes('code')) {
|
|
372
|
+
window.history.pushState({}, document.title, "/");
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
setUser(user)
|
|
376
|
+
setIsSignedIn(true)
|
|
377
|
+
|
|
378
|
+
setIsAuthReady(true)
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
async function checkToken() {
|
|
383
|
+
if (!token) {
|
|
384
|
+
log('error: no user token found')
|
|
385
|
+
|
|
386
|
+
setIsAuthReady(true)
|
|
387
|
+
return
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const decoded = jwtDecode(token?.access_token)
|
|
391
|
+
const isExpired = decoded.exp && decoded.exp < Date.now() / 1000
|
|
392
|
+
|
|
393
|
+
if (isExpired) {
|
|
394
|
+
log('token is expired - refreshing ...')
|
|
395
|
+
const newToken = await fetchToken(token?.refresh)
|
|
396
|
+
fetchUser(newToken.access_token)
|
|
397
|
+
} else {
|
|
398
|
+
fetchUser(token.access_token)
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (token) {
|
|
403
|
+
checkToken()
|
|
404
|
+
}
|
|
405
|
+
}, [token])
|
|
406
|
+
|
|
280
407
|
const connectToDb = async () => {
|
|
281
408
|
const tok = await getToken()
|
|
282
409
|
if (!tok) {
|
|
@@ -401,97 +528,6 @@ export function BasicProvider({ children, project_id, schema, debug = false }: {
|
|
|
401
528
|
return token
|
|
402
529
|
}
|
|
403
530
|
|
|
404
|
-
useEffect(() => {
|
|
405
|
-
localStorage.setItem('basic_debug', debug ? 'true' : 'false')
|
|
406
|
-
|
|
407
|
-
try {
|
|
408
|
-
if (window.location.search.includes('code')) {
|
|
409
|
-
let code = window.location?.search?.split('code=')[1].split('&')[0]
|
|
410
|
-
|
|
411
|
-
const state = localStorage.getItem('basic_auth_state')
|
|
412
|
-
if (!state || state !== window.location.search.split('state=')[1].split('&')[0]) {
|
|
413
|
-
log('error: auth state does not match')
|
|
414
|
-
setIsAuthReady(true)
|
|
415
|
-
|
|
416
|
-
localStorage.removeItem('basic_auth_state')
|
|
417
|
-
window.history.pushState({}, document.title, "/");
|
|
418
|
-
return
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
localStorage.removeItem('basic_auth_state')
|
|
422
|
-
|
|
423
|
-
fetchToken(code)
|
|
424
|
-
} else {
|
|
425
|
-
let cookie_token = getCookie('basic_token')
|
|
426
|
-
if (cookie_token !== '') {
|
|
427
|
-
setToken(JSON.parse(cookie_token))
|
|
428
|
-
} else {
|
|
429
|
-
setIsAuthReady(true)
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
} catch (e) {
|
|
435
|
-
log('error getting cookie', e)
|
|
436
|
-
}
|
|
437
|
-
}, [])
|
|
438
|
-
|
|
439
|
-
useEffect(() => {
|
|
440
|
-
async function fetchUser(acc_token: string) {
|
|
441
|
-
console.info('fetching user')
|
|
442
|
-
const user = await fetch('https://api.basic.tech/auth/userInfo', {
|
|
443
|
-
method: 'GET',
|
|
444
|
-
headers: {
|
|
445
|
-
'Authorization': `Bearer ${acc_token}`
|
|
446
|
-
}
|
|
447
|
-
})
|
|
448
|
-
.then(response => response.json())
|
|
449
|
-
.catch(error => log('Error:', error))
|
|
450
|
-
|
|
451
|
-
if (user.error) {
|
|
452
|
-
log('error fetching user', user.error)
|
|
453
|
-
// refreshToken()
|
|
454
|
-
return
|
|
455
|
-
} else {
|
|
456
|
-
// log('user', user)
|
|
457
|
-
document.cookie = `basic_token=${JSON.stringify(token)}; Secure; SameSite=Strict`;
|
|
458
|
-
|
|
459
|
-
if (window.location.search.includes('code')) {
|
|
460
|
-
window.history.pushState({}, document.title, "/");
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
setUser(user)
|
|
464
|
-
setIsSignedIn(true)
|
|
465
|
-
|
|
466
|
-
setIsAuthReady(true)
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
async function checkToken() {
|
|
471
|
-
if (!token) {
|
|
472
|
-
log('error: no user token found')
|
|
473
|
-
|
|
474
|
-
setIsAuthReady(true)
|
|
475
|
-
return
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
const decoded = jwtDecode(token?.access_token)
|
|
479
|
-
const isExpired = decoded.exp && decoded.exp < Date.now() / 1000
|
|
480
|
-
|
|
481
|
-
if (isExpired) {
|
|
482
|
-
log('token is expired - refreshing ...')
|
|
483
|
-
const newToken = await fetchToken(token?.refresh)
|
|
484
|
-
fetchUser(newToken.access_token)
|
|
485
|
-
} else {
|
|
486
|
-
fetchUser(token.access_token)
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
if (token) {
|
|
491
|
-
checkToken()
|
|
492
|
-
}
|
|
493
|
-
}, [token])
|
|
494
|
-
|
|
495
531
|
|
|
496
532
|
const db_ = (tableName: string) => {
|
|
497
533
|
const checkSignIn = () => {
|