@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.
@@ -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: string, schema?: any, debug?: boolean }) {
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
- const schemaStatus = await getSchemaStatus(schema)
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
- setIsReady(true)
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 = () => {