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