@basictech/react 0.5.0-beta.2 → 0.5.0-beta.4
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 +2 -2
- package/src/AuthContext.tsx +141 -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,43 @@ 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
|
+
}
|
|
204
|
+
console.warn('[basic] New version available:', latestVersion, `\nrun "npm install @basictech/react@${latestVersion}" to update`);
|
|
205
|
+
|
|
206
|
+
if (isBeta) {
|
|
207
|
+
log('thank you for being on basictech/react beta :)')
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
hasNewVersion: currentVersion !== latestVersion,
|
|
212
|
+
latestVersion,
|
|
213
|
+
currentVersion
|
|
214
|
+
};
|
|
215
|
+
} catch (error) {
|
|
216
|
+
log('Error checking for new version:', error);
|
|
217
|
+
return {
|
|
218
|
+
hasNewVersion: false,
|
|
219
|
+
latestVersion: null,
|
|
220
|
+
currentVersion: null
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
196
224
|
|
|
197
|
-
export function BasicProvider({ children, project_id, schema, debug = false }: { children: React.ReactNode, project_id
|
|
225
|
+
export function BasicProvider({ children, project_id, schema, debug = false }: { children: React.ReactNode, project_id?: string, schema?: any, debug?: boolean }) {
|
|
198
226
|
const [isAuthReady, setIsAuthReady] = useState(false)
|
|
199
227
|
const [isSignedIn, setIsSignedIn] = useState<boolean>(false)
|
|
200
228
|
const [token, setToken] = useState<Token | null>(null)
|
|
@@ -208,7 +236,7 @@ export function BasicProvider({ children, project_id, schema, debug = false }: {
|
|
|
208
236
|
const syncRef = useRef<BasicSync | null>(null);
|
|
209
237
|
|
|
210
238
|
useEffect(() => {
|
|
211
|
-
function initDb() {
|
|
239
|
+
function initDb(options: { shouldConnect: boolean }) {
|
|
212
240
|
if (!syncRef.current) {
|
|
213
241
|
log('Initializing BasicDB')
|
|
214
242
|
syncRef.current = new BasicSync('basicdb', { schema: schema });
|
|
@@ -221,8 +249,12 @@ export function BasicProvider({ children, project_id, schema, debug = false }: {
|
|
|
221
249
|
setDbStatus(getSyncStatus(status))
|
|
222
250
|
})
|
|
223
251
|
|
|
252
|
+
if (options.shouldConnect) {
|
|
253
|
+
setShouldConnect(true)
|
|
254
|
+
} else {
|
|
255
|
+
log('Sync is disabled')
|
|
256
|
+
}
|
|
224
257
|
|
|
225
|
-
setShouldConnect(true)
|
|
226
258
|
setIsReady(true)
|
|
227
259
|
|
|
228
260
|
// log('db is open', syncRef.current.isOpen())
|
|
@@ -254,13 +286,18 @@ export function BasicProvider({ children, project_id, schema, debug = false }: {
|
|
|
254
286
|
}
|
|
255
287
|
|
|
256
288
|
|
|
257
|
-
|
|
289
|
+
let schemaStatus = { valid: false }
|
|
290
|
+
if (schema.version !== 0) {
|
|
291
|
+
schemaStatus = await getSchemaStatus(schema)
|
|
292
|
+
}
|
|
258
293
|
|
|
259
294
|
if (schemaStatus.valid) {
|
|
260
|
-
initDb()
|
|
295
|
+
initDb({ shouldConnect: true })
|
|
261
296
|
} else {
|
|
262
|
-
|
|
297
|
+
initDb({ shouldConnect: false })
|
|
263
298
|
}
|
|
299
|
+
|
|
300
|
+
checkForNewVersion()
|
|
264
301
|
}
|
|
265
302
|
|
|
266
303
|
if (schema) {
|
|
@@ -277,6 +314,97 @@ export function BasicProvider({ children, project_id, schema, debug = false }: {
|
|
|
277
314
|
}
|
|
278
315
|
}, [isSignedIn, shouldConnect])
|
|
279
316
|
|
|
317
|
+
useEffect(() => {
|
|
318
|
+
localStorage.setItem('basic_debug', debug ? 'true' : 'false')
|
|
319
|
+
|
|
320
|
+
try {
|
|
321
|
+
if (window.location.search.includes('code')) {
|
|
322
|
+
let code = window.location?.search?.split('code=')[1].split('&')[0]
|
|
323
|
+
|
|
324
|
+
const state = localStorage.getItem('basic_auth_state')
|
|
325
|
+
if (!state || state !== window.location.search.split('state=')[1].split('&')[0]) {
|
|
326
|
+
log('error: auth state does not match')
|
|
327
|
+
setIsAuthReady(true)
|
|
328
|
+
|
|
329
|
+
localStorage.removeItem('basic_auth_state')
|
|
330
|
+
window.history.pushState({}, document.title, "/");
|
|
331
|
+
return
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
localStorage.removeItem('basic_auth_state')
|
|
335
|
+
|
|
336
|
+
fetchToken(code)
|
|
337
|
+
} else {
|
|
338
|
+
let cookie_token = getCookie('basic_token')
|
|
339
|
+
if (cookie_token !== '') {
|
|
340
|
+
setToken(JSON.parse(cookie_token))
|
|
341
|
+
} else {
|
|
342
|
+
setIsAuthReady(true)
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
} catch (e) {
|
|
348
|
+
log('error getting cookie', e)
|
|
349
|
+
}
|
|
350
|
+
}, [])
|
|
351
|
+
|
|
352
|
+
useEffect(() => {
|
|
353
|
+
async function fetchUser(acc_token: string) {
|
|
354
|
+
console.info('fetching user')
|
|
355
|
+
const user = await fetch('https://api.basic.tech/auth/userInfo', {
|
|
356
|
+
method: 'GET',
|
|
357
|
+
headers: {
|
|
358
|
+
'Authorization': `Bearer ${acc_token}`
|
|
359
|
+
}
|
|
360
|
+
})
|
|
361
|
+
.then(response => response.json())
|
|
362
|
+
.catch(error => log('Error:', error))
|
|
363
|
+
|
|
364
|
+
if (user.error) {
|
|
365
|
+
log('error fetching user', user.error)
|
|
366
|
+
// refreshToken()
|
|
367
|
+
return
|
|
368
|
+
} else {
|
|
369
|
+
// log('user', user)
|
|
370
|
+
document.cookie = `basic_token=${JSON.stringify(token)}; Secure; SameSite=Strict`;
|
|
371
|
+
|
|
372
|
+
if (window.location.search.includes('code')) {
|
|
373
|
+
window.history.pushState({}, document.title, "/");
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
setUser(user)
|
|
377
|
+
setIsSignedIn(true)
|
|
378
|
+
|
|
379
|
+
setIsAuthReady(true)
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async function checkToken() {
|
|
384
|
+
if (!token) {
|
|
385
|
+
log('error: no user token found')
|
|
386
|
+
|
|
387
|
+
setIsAuthReady(true)
|
|
388
|
+
return
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const decoded = jwtDecode(token?.access_token)
|
|
392
|
+
const isExpired = decoded.exp && decoded.exp < Date.now() / 1000
|
|
393
|
+
|
|
394
|
+
if (isExpired) {
|
|
395
|
+
log('token is expired - refreshing ...')
|
|
396
|
+
const newToken = await fetchToken(token?.refresh)
|
|
397
|
+
fetchUser(newToken.access_token)
|
|
398
|
+
} else {
|
|
399
|
+
fetchUser(token.access_token)
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (token) {
|
|
404
|
+
checkToken()
|
|
405
|
+
}
|
|
406
|
+
}, [token])
|
|
407
|
+
|
|
280
408
|
const connectToDb = async () => {
|
|
281
409
|
const tok = await getToken()
|
|
282
410
|
if (!tok) {
|
|
@@ -401,97 +529,6 @@ export function BasicProvider({ children, project_id, schema, debug = false }: {
|
|
|
401
529
|
return token
|
|
402
530
|
}
|
|
403
531
|
|
|
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
532
|
|
|
496
533
|
const db_ = (tableName: string) => {
|
|
497
534
|
const checkSignIn = () => {
|