@basictech/react 0.7.0-beta.2 → 0.7.0-beta.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/AUTH_IMPLEMENTATION_GUIDE.md +2009 -0
- package/changelog.md +6 -0
- package/dist/index.d.mts +1 -106
- package/dist/index.d.ts +1 -106
- package/dist/index.js +17 -381
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +17 -380
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/AuthContext.tsx +74 -12
- package/src/index.ts +5 -1
- package/src/utils/storage.ts +1 -0
package/dist/index.mjs
CHANGED
|
@@ -250,363 +250,8 @@ var BasicSync = class extends Dexie2 {
|
|
|
250
250
|
}
|
|
251
251
|
};
|
|
252
252
|
|
|
253
|
-
// src/db_ts.ts
|
|
254
|
-
var DBError = class extends Error {
|
|
255
|
-
constructor(message, status, response, originalError) {
|
|
256
|
-
super(message);
|
|
257
|
-
this.status = status;
|
|
258
|
-
this.response = response;
|
|
259
|
-
this.originalError = originalError;
|
|
260
|
-
this.name = "DBError";
|
|
261
|
-
}
|
|
262
|
-
};
|
|
263
|
-
var QueryBuilder = class {
|
|
264
|
-
constructor(tableClient, tableSchema) {
|
|
265
|
-
this.tableClient = tableClient;
|
|
266
|
-
this.tableSchema = tableSchema;
|
|
267
|
-
}
|
|
268
|
-
params = {};
|
|
269
|
-
// Reserved fields that are always allowed
|
|
270
|
-
reservedFields = ["created_at", "updated_at", "id"];
|
|
271
|
-
// Validate field existence in schema
|
|
272
|
-
validateField(field) {
|
|
273
|
-
if (this.tableSchema && !this.reservedFields.includes(field)) {
|
|
274
|
-
if (!this.tableSchema.fields || !(field in this.tableSchema.fields)) {
|
|
275
|
-
throw new Error(`Invalid field: "${field}". Field does not exist in table schema.`);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
// Validate operator based on field type
|
|
280
|
-
validateOperator(field, operator, value) {
|
|
281
|
-
if (!this.tableSchema || this.reservedFields.includes(field)) {
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
const fieldInfo = this.tableSchema.fields[field];
|
|
285
|
-
if (!fieldInfo)
|
|
286
|
-
return;
|
|
287
|
-
switch (operator) {
|
|
288
|
-
case "gt":
|
|
289
|
-
case "gte":
|
|
290
|
-
case "lt":
|
|
291
|
-
case "lte":
|
|
292
|
-
if (fieldInfo.type !== "number" && fieldInfo.type !== "string") {
|
|
293
|
-
throw new Error(`Operator "${operator}" can only be used with number or string fields. Field "${field}" is type "${fieldInfo.type}".`);
|
|
294
|
-
}
|
|
295
|
-
break;
|
|
296
|
-
case "like":
|
|
297
|
-
case "ilike":
|
|
298
|
-
if (fieldInfo.type !== "string") {
|
|
299
|
-
throw new Error(`Operator "${operator}" can only be used with string fields. Field "${field}" is type "${fieldInfo.type}".`);
|
|
300
|
-
}
|
|
301
|
-
if (typeof value !== "string") {
|
|
302
|
-
throw new Error(`Operator "${operator}" requires a string value. Received: ${typeof value}`);
|
|
303
|
-
}
|
|
304
|
-
break;
|
|
305
|
-
case "in":
|
|
306
|
-
if (!Array.isArray(value)) {
|
|
307
|
-
throw new Error(`Operator "in" requires an array value. Received: ${typeof value}`);
|
|
308
|
-
}
|
|
309
|
-
break;
|
|
310
|
-
case "is":
|
|
311
|
-
if (value !== null && typeof value !== "boolean") {
|
|
312
|
-
throw new Error(`Operator "is" requires null or boolean. Received: ${typeof value}`);
|
|
313
|
-
}
|
|
314
|
-
break;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
// Add ordering to query with schema validation
|
|
318
|
-
order(field, direction = "asc") {
|
|
319
|
-
this.validateField(field);
|
|
320
|
-
this.params.order = `${field}.${direction}`;
|
|
321
|
-
return this;
|
|
322
|
-
}
|
|
323
|
-
// Add filtering to query
|
|
324
|
-
filter(conditions) {
|
|
325
|
-
if (!this.params.filters) {
|
|
326
|
-
this.params.filters = {};
|
|
327
|
-
}
|
|
328
|
-
for (const [field, condition] of Object.entries(conditions)) {
|
|
329
|
-
this.validateField(field);
|
|
330
|
-
if (condition === null || typeof condition !== "object") {
|
|
331
|
-
this.params.filters[field] = condition;
|
|
332
|
-
} else {
|
|
333
|
-
this.params.filters[field] = condition;
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
return this;
|
|
337
|
-
}
|
|
338
|
-
// Add limit to query
|
|
339
|
-
limit(count) {
|
|
340
|
-
this.params.limit = count;
|
|
341
|
-
return this;
|
|
342
|
-
}
|
|
343
|
-
// Add offset to query for pagination
|
|
344
|
-
offset(count) {
|
|
345
|
-
this.params.offset = count;
|
|
346
|
-
return this;
|
|
347
|
-
}
|
|
348
|
-
// Auto-execute when awaited
|
|
349
|
-
then(onfulfilled, onrejected) {
|
|
350
|
-
return this.tableClient.executeQuery(this.params).then(onfulfilled, onrejected);
|
|
351
|
-
}
|
|
352
|
-
// Auto-execute when awaited with catch
|
|
353
|
-
catch(onrejected) {
|
|
354
|
-
return this.tableClient.executeQuery(this.params).catch(onrejected);
|
|
355
|
-
}
|
|
356
|
-
// Auto-execute when awaited with finally
|
|
357
|
-
finally(onfinally) {
|
|
358
|
-
return this.tableClient.executeQuery(this.params).finally(onfinally);
|
|
359
|
-
}
|
|
360
|
-
};
|
|
361
|
-
var TableClient = class {
|
|
362
|
-
constructor(baseUrl, projectId, token, table, getToken, schema) {
|
|
363
|
-
this.baseUrl = baseUrl;
|
|
364
|
-
this.projectId = projectId;
|
|
365
|
-
this.token = token;
|
|
366
|
-
this.table = table;
|
|
367
|
-
this.getToken = getToken;
|
|
368
|
-
this.schema = schema;
|
|
369
|
-
if (schema && schema.tables && schema.tables[table]) {
|
|
370
|
-
this.tableSchema = schema.tables[table];
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
tableSchema;
|
|
374
|
-
async headers() {
|
|
375
|
-
const token = await this.getToken();
|
|
376
|
-
return {
|
|
377
|
-
Authorization: `Bearer ${token}`,
|
|
378
|
-
"Content-Type": "application/json"
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
async handleRequest(request) {
|
|
382
|
-
try {
|
|
383
|
-
const res = await request;
|
|
384
|
-
if (!res.ok) {
|
|
385
|
-
let errorMessage = `Request failed with status ${res.status}`;
|
|
386
|
-
let errorData;
|
|
387
|
-
try {
|
|
388
|
-
const json2 = await res.json();
|
|
389
|
-
errorData = json2;
|
|
390
|
-
if (json2.error || json2.message) {
|
|
391
|
-
const errorDetails = typeof json2.error === "object" ? JSON.stringify(json2.error) : json2.error;
|
|
392
|
-
const messageDetails = typeof json2.message === "object" ? JSON.stringify(json2.message) : json2.message;
|
|
393
|
-
errorMessage = `${res.status} ${res.statusText}: ${messageDetails || errorDetails || "Unknown error"}`;
|
|
394
|
-
}
|
|
395
|
-
} catch (e) {
|
|
396
|
-
console.log("Failed to parse error response:", e);
|
|
397
|
-
errorMessage = `${res.status} ${res.statusText}`;
|
|
398
|
-
}
|
|
399
|
-
throw new DBError(
|
|
400
|
-
errorMessage,
|
|
401
|
-
res.status,
|
|
402
|
-
errorData
|
|
403
|
-
);
|
|
404
|
-
}
|
|
405
|
-
const json = await res.json();
|
|
406
|
-
return json.data;
|
|
407
|
-
} catch (error) {
|
|
408
|
-
console.log("Caught error:", error);
|
|
409
|
-
if (error instanceof Error) {
|
|
410
|
-
console.log("Error type:", error.constructor.name);
|
|
411
|
-
console.log("Error stack:", error.stack);
|
|
412
|
-
}
|
|
413
|
-
if (error instanceof DBError) {
|
|
414
|
-
throw error;
|
|
415
|
-
}
|
|
416
|
-
if (error instanceof TypeError && error.message === "Network request failed") {
|
|
417
|
-
throw new DBError(
|
|
418
|
-
"Network request failed. Please check your internet connection and try again.",
|
|
419
|
-
void 0,
|
|
420
|
-
void 0,
|
|
421
|
-
error
|
|
422
|
-
);
|
|
423
|
-
}
|
|
424
|
-
throw new DBError(
|
|
425
|
-
`Unexpected error: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
426
|
-
void 0,
|
|
427
|
-
void 0,
|
|
428
|
-
error instanceof Error ? error : void 0
|
|
429
|
-
);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
// Build query string from query options
|
|
433
|
-
buildQueryParams(query) {
|
|
434
|
-
if (!query)
|
|
435
|
-
return "";
|
|
436
|
-
const params = [];
|
|
437
|
-
if (query.id) {
|
|
438
|
-
params.push(`id=${query.id}`);
|
|
439
|
-
}
|
|
440
|
-
if (query.filters) {
|
|
441
|
-
for (const [field, condition] of Object.entries(query.filters)) {
|
|
442
|
-
this.addFilterParam(params, field, condition);
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
if (query.order) {
|
|
446
|
-
params.push(`order=${query.order}`);
|
|
447
|
-
}
|
|
448
|
-
if (query.limit !== void 0 && query.limit >= 0) {
|
|
449
|
-
params.push(`limit=${query.limit}`);
|
|
450
|
-
}
|
|
451
|
-
if (query.offset !== void 0 && query.offset >= 0) {
|
|
452
|
-
params.push(`offset=${query.offset}`);
|
|
453
|
-
}
|
|
454
|
-
return params.length > 0 ? `?${params.join("&")}` : "";
|
|
455
|
-
}
|
|
456
|
-
// Helper method to build filter parameters
|
|
457
|
-
addFilterParam(params, field, condition, negate = false) {
|
|
458
|
-
if (condition === null || typeof condition !== "object") {
|
|
459
|
-
if (condition === null) {
|
|
460
|
-
params.push(`${field}=${negate ? "not." : ""}is.null`);
|
|
461
|
-
} else if (typeof condition === "boolean") {
|
|
462
|
-
params.push(`${field}=${negate ? "not." : ""}is.${condition}`);
|
|
463
|
-
} else if (typeof condition === "number") {
|
|
464
|
-
params.push(`${field}=${negate ? "not." : ""}eq.${condition}`);
|
|
465
|
-
} else {
|
|
466
|
-
params.push(`${field}=${negate ? "not." : ""}eq.${encodeURIComponent(String(condition))}`);
|
|
467
|
-
}
|
|
468
|
-
return;
|
|
469
|
-
}
|
|
470
|
-
const operatorObj = condition;
|
|
471
|
-
if (operatorObj.not) {
|
|
472
|
-
this.addFilterParam(params, field, operatorObj.not, true);
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
|
-
for (const [op, value] of Object.entries(operatorObj)) {
|
|
476
|
-
if (op === "not")
|
|
477
|
-
continue;
|
|
478
|
-
const operator = op;
|
|
479
|
-
if (value === null) {
|
|
480
|
-
params.push(`${field}=${negate ? "not." : ""}is.null`);
|
|
481
|
-
} else if (operator === "in" && Array.isArray(value)) {
|
|
482
|
-
params.push(`${field}=${negate ? "not." : ""}in.${value.join(",")}`);
|
|
483
|
-
} else if (operator === "is") {
|
|
484
|
-
if (typeof value === "boolean") {
|
|
485
|
-
params.push(`${field}=${negate ? "not." : ""}is.${value}`);
|
|
486
|
-
} else {
|
|
487
|
-
params.push(`${field}=${negate ? "not." : ""}is.null`);
|
|
488
|
-
}
|
|
489
|
-
} else {
|
|
490
|
-
const paramValue = typeof value === "string" ? encodeURIComponent(value) : String(value);
|
|
491
|
-
params.push(`${field}=${negate ? "not." : ""}${operator}.${paramValue}`);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
// Internal method to execute a query with options
|
|
496
|
-
async executeQuery(options) {
|
|
497
|
-
const params = this.buildQueryParams(options);
|
|
498
|
-
const headers = await this.headers();
|
|
499
|
-
return this.handleRequest(
|
|
500
|
-
fetch(`${this.baseUrl}/account/${this.projectId}/db/${this.table}${params}`, {
|
|
501
|
-
headers
|
|
502
|
-
})
|
|
503
|
-
);
|
|
504
|
-
}
|
|
505
|
-
// Public method to start building a query
|
|
506
|
-
getAll() {
|
|
507
|
-
return new QueryBuilder(this, this.tableSchema);
|
|
508
|
-
}
|
|
509
|
-
// Get a specific item by ID
|
|
510
|
-
async get(id) {
|
|
511
|
-
const headers = await this.headers();
|
|
512
|
-
return this.handleRequest(
|
|
513
|
-
fetch(`${this.baseUrl}/account/${this.projectId}/db/${this.table}/${id}`, {
|
|
514
|
-
headers
|
|
515
|
-
})
|
|
516
|
-
);
|
|
517
|
-
}
|
|
518
|
-
async create(value) {
|
|
519
|
-
const headers = await this.headers();
|
|
520
|
-
return this.handleRequest(
|
|
521
|
-
fetch(`${this.baseUrl}/account/${this.projectId}/db/${this.table}`, {
|
|
522
|
-
method: "POST",
|
|
523
|
-
headers,
|
|
524
|
-
body: JSON.stringify({ value })
|
|
525
|
-
})
|
|
526
|
-
);
|
|
527
|
-
}
|
|
528
|
-
async update(id, value) {
|
|
529
|
-
const headers = await this.headers();
|
|
530
|
-
return this.handleRequest(
|
|
531
|
-
fetch(`${this.baseUrl}/account/${this.projectId}/db/${this.table}/${id}`, {
|
|
532
|
-
method: "PATCH",
|
|
533
|
-
headers,
|
|
534
|
-
body: JSON.stringify({ value })
|
|
535
|
-
})
|
|
536
|
-
);
|
|
537
|
-
}
|
|
538
|
-
async replace(id, value) {
|
|
539
|
-
const headers = await this.headers();
|
|
540
|
-
return this.handleRequest(
|
|
541
|
-
fetch(`${this.baseUrl}/account/${this.projectId}/db/${this.table}/${id}`, {
|
|
542
|
-
method: "PUT",
|
|
543
|
-
headers,
|
|
544
|
-
body: JSON.stringify({ value })
|
|
545
|
-
})
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
async delete(id) {
|
|
549
|
-
const token = await this.getToken();
|
|
550
|
-
const headers = {
|
|
551
|
-
Authorization: `Bearer ${token}`
|
|
552
|
-
};
|
|
553
|
-
return this.handleRequest(
|
|
554
|
-
fetch(`${this.baseUrl}/account/${this.projectId}/db/${this.table}/${id}`, {
|
|
555
|
-
method: "DELETE",
|
|
556
|
-
headers
|
|
557
|
-
})
|
|
558
|
-
);
|
|
559
|
-
}
|
|
560
|
-
};
|
|
561
|
-
var BasicDBSDK = class {
|
|
562
|
-
projectId;
|
|
563
|
-
getToken;
|
|
564
|
-
baseUrl;
|
|
565
|
-
schema;
|
|
566
|
-
tableNames;
|
|
567
|
-
constructor(config) {
|
|
568
|
-
this.projectId = config.project_id;
|
|
569
|
-
if (config.getToken) {
|
|
570
|
-
this.getToken = config.getToken;
|
|
571
|
-
} else if (config.token) {
|
|
572
|
-
this.getToken = async () => config.token;
|
|
573
|
-
} else {
|
|
574
|
-
throw new Error("Either token or getToken must be provided");
|
|
575
|
-
}
|
|
576
|
-
this.baseUrl = config.baseUrl || "https://api.basic.tech";
|
|
577
|
-
this.schema = config.schema;
|
|
578
|
-
this.tableNames = Object.keys(this.schema.tables);
|
|
579
|
-
}
|
|
580
|
-
// Primary method - table access
|
|
581
|
-
table(name) {
|
|
582
|
-
if (!this.tableNames.includes(name)) {
|
|
583
|
-
throw new Error(`Table '${name}' not found in schema. Available tables: ${this.tableNames.join(", ")}`);
|
|
584
|
-
}
|
|
585
|
-
return new TableClient(
|
|
586
|
-
this.baseUrl,
|
|
587
|
-
this.projectId,
|
|
588
|
-
"",
|
|
589
|
-
// Empty placeholder, will be replaced in headers() method
|
|
590
|
-
name,
|
|
591
|
-
this.getToken,
|
|
592
|
-
this.schema
|
|
593
|
-
// Pass the entire schema to the TableClient
|
|
594
|
-
);
|
|
595
|
-
}
|
|
596
|
-
get tables() {
|
|
597
|
-
return {};
|
|
598
|
-
}
|
|
599
|
-
fields(table) {
|
|
600
|
-
const tableSchema = this.schema.tables[table];
|
|
601
|
-
if (!tableSchema) {
|
|
602
|
-
throw new Error(`Table '${table}' not found in schema`);
|
|
603
|
-
}
|
|
604
|
-
return Object.keys(tableSchema.fields);
|
|
605
|
-
}
|
|
606
|
-
};
|
|
607
|
-
|
|
608
253
|
// package.json
|
|
609
|
-
var version = "0.7.0-beta.
|
|
254
|
+
var version = "0.7.0-beta.2";
|
|
610
255
|
|
|
611
256
|
// src/updater/versionUpdater.ts
|
|
612
257
|
var VersionUpdater = class {
|
|
@@ -959,7 +604,6 @@ var BasicContext = createContext({
|
|
|
959
604
|
}),
|
|
960
605
|
getSignInLink: () => Promise.resolve(""),
|
|
961
606
|
db: {},
|
|
962
|
-
remoteDb: {},
|
|
963
607
|
dbStatus: "LOADING" /* LOADING */
|
|
964
608
|
});
|
|
965
609
|
function BasicProvider({
|
|
@@ -980,7 +624,6 @@ function BasicProvider({
|
|
|
980
624
|
const [isOnline, setIsOnline] = useState(navigator.onLine);
|
|
981
625
|
const [pendingRefresh, setPendingRefresh] = useState(false);
|
|
982
626
|
const syncRef = useRef(null);
|
|
983
|
-
const remoteDbRef = useRef(null);
|
|
984
627
|
const storageAdapter = storage || new LocalStorageAdapter();
|
|
985
628
|
const isDevMode = () => isDevelopment(debug);
|
|
986
629
|
const cleanOAuthParams = () => cleanOAuthParamsFromUrl();
|
|
@@ -994,7 +637,7 @@ function BasicProvider({
|
|
|
994
637
|
if (token) {
|
|
995
638
|
const refreshToken = token.refresh_token || localStorage.getItem("basic_refresh_token");
|
|
996
639
|
if (refreshToken) {
|
|
997
|
-
fetchToken(refreshToken).catch((error2) => {
|
|
640
|
+
fetchToken(refreshToken, true).catch((error2) => {
|
|
998
641
|
log("Retry refresh failed:", error2);
|
|
999
642
|
});
|
|
1000
643
|
}
|
|
@@ -1076,17 +719,6 @@ function BasicProvider({
|
|
|
1076
719
|
}
|
|
1077
720
|
connectToDb();
|
|
1078
721
|
}, [isSignedIn, shouldConnect]);
|
|
1079
|
-
useEffect(() => {
|
|
1080
|
-
if (project_id && schema && token?.access_token && !remoteDbRef.current) {
|
|
1081
|
-
log("Initializing Remote DB SDK");
|
|
1082
|
-
remoteDbRef.current = new BasicDBSDK({
|
|
1083
|
-
project_id,
|
|
1084
|
-
schema,
|
|
1085
|
-
getToken: () => getToken(),
|
|
1086
|
-
baseUrl: "https://api.basic.tech"
|
|
1087
|
-
});
|
|
1088
|
-
}
|
|
1089
|
-
}, [token, project_id, schema]);
|
|
1090
722
|
useEffect(() => {
|
|
1091
723
|
const initializeAuth = async () => {
|
|
1092
724
|
await storageAdapter.set(STORAGE_KEYS.DEBUG, debug ? "true" : "false");
|
|
@@ -1117,14 +749,14 @@ function BasicProvider({
|
|
|
1117
749
|
}
|
|
1118
750
|
await storageAdapter.remove(STORAGE_KEYS.AUTH_STATE);
|
|
1119
751
|
cleanOAuthParams();
|
|
1120
|
-
fetchToken(code).catch((error2) => {
|
|
752
|
+
fetchToken(code, false).catch((error2) => {
|
|
1121
753
|
log("Error fetching token:", error2);
|
|
1122
754
|
});
|
|
1123
755
|
} else {
|
|
1124
756
|
const refreshToken = await storageAdapter.get(STORAGE_KEYS.REFRESH_TOKEN);
|
|
1125
757
|
if (refreshToken) {
|
|
1126
758
|
log("Found refresh token in storage, attempting to refresh access token");
|
|
1127
|
-
fetchToken(refreshToken).catch((error2) => {
|
|
759
|
+
fetchToken(refreshToken, true).catch((error2) => {
|
|
1128
760
|
log("Error fetching refresh token:", error2);
|
|
1129
761
|
});
|
|
1130
762
|
} else {
|
|
@@ -1193,7 +825,7 @@ function BasicProvider({
|
|
|
1193
825
|
if (isExpired) {
|
|
1194
826
|
log("token is expired - refreshing ...");
|
|
1195
827
|
try {
|
|
1196
|
-
const newToken = await fetchToken(token?.refresh_token || "");
|
|
828
|
+
const newToken = await fetchToken(token?.refresh_token || "", true);
|
|
1197
829
|
fetchUser(newToken?.access_token || "");
|
|
1198
830
|
} catch (error2) {
|
|
1199
831
|
log("Failed to refresh token in checkToken:", error2);
|
|
@@ -1278,7 +910,7 @@ function BasicProvider({
|
|
|
1278
910
|
}
|
|
1279
911
|
await storageAdapter.remove(STORAGE_KEYS.AUTH_STATE);
|
|
1280
912
|
cleanOAuthParams();
|
|
1281
|
-
const token2 = await fetchToken(code);
|
|
913
|
+
const token2 = await fetchToken(code, false);
|
|
1282
914
|
if (token2) {
|
|
1283
915
|
log("signinWithCode successful");
|
|
1284
916
|
return { success: true };
|
|
@@ -1323,7 +955,7 @@ function BasicProvider({
|
|
|
1323
955
|
if (refreshToken) {
|
|
1324
956
|
log("No token in memory, attempting to refresh from storage");
|
|
1325
957
|
try {
|
|
1326
|
-
const newToken = await fetchToken(refreshToken);
|
|
958
|
+
const newToken = await fetchToken(refreshToken, true);
|
|
1327
959
|
if (newToken?.access_token) {
|
|
1328
960
|
return newToken.access_token;
|
|
1329
961
|
}
|
|
@@ -1350,7 +982,7 @@ function BasicProvider({
|
|
|
1350
982
|
const refreshToken = token?.refresh_token || await storageAdapter.get(STORAGE_KEYS.REFRESH_TOKEN);
|
|
1351
983
|
if (refreshToken) {
|
|
1352
984
|
try {
|
|
1353
|
-
const newToken = await fetchToken(refreshToken);
|
|
985
|
+
const newToken = await fetchToken(refreshToken, true);
|
|
1354
986
|
return newToken?.access_token || "";
|
|
1355
987
|
} catch (error2) {
|
|
1356
988
|
log("Failed to refresh expired token:", error2);
|
|
@@ -1366,19 +998,26 @@ function BasicProvider({
|
|
|
1366
998
|
}
|
|
1367
999
|
return token?.access_token || "";
|
|
1368
1000
|
};
|
|
1369
|
-
const fetchToken = async (
|
|
1001
|
+
const fetchToken = async (codeOrRefreshToken, isRefreshToken = false) => {
|
|
1370
1002
|
try {
|
|
1371
1003
|
if (!isOnline) {
|
|
1372
1004
|
log("Network is offline, marking refresh as pending");
|
|
1373
1005
|
setPendingRefresh(true);
|
|
1374
1006
|
throw new Error("Network offline - refresh will be retried when online");
|
|
1375
1007
|
}
|
|
1008
|
+
const requestBody = isRefreshToken ? {
|
|
1009
|
+
grant_type: "refresh_token",
|
|
1010
|
+
refresh_token: codeOrRefreshToken
|
|
1011
|
+
} : {
|
|
1012
|
+
grant_type: "authorization_code",
|
|
1013
|
+
code: codeOrRefreshToken
|
|
1014
|
+
};
|
|
1376
1015
|
const token2 = await fetch("https://api.basic.tech/auth/token", {
|
|
1377
1016
|
method: "POST",
|
|
1378
1017
|
headers: {
|
|
1379
1018
|
"Content-Type": "application/json"
|
|
1380
1019
|
},
|
|
1381
|
-
body: JSON.stringify(
|
|
1020
|
+
body: JSON.stringify(requestBody)
|
|
1382
1021
|
}).then((response) => response.json()).catch((error2) => {
|
|
1383
1022
|
log("Network error fetching token:", error2);
|
|
1384
1023
|
if (!isOnline) {
|
|
@@ -1444,7 +1083,6 @@ function BasicProvider({
|
|
|
1444
1083
|
getToken,
|
|
1445
1084
|
getSignInLink,
|
|
1446
1085
|
db: syncRef.current ? syncRef.current : noDb,
|
|
1447
|
-
remoteDb: remoteDbRef.current ? remoteDbRef.current : noDb,
|
|
1448
1086
|
dbStatus
|
|
1449
1087
|
}, children: [
|
|
1450
1088
|
error && isDevMode() && /* @__PURE__ */ jsx(ErrorDisplay, { error }),
|
|
@@ -1481,7 +1119,6 @@ function useBasic() {
|
|
|
1481
1119
|
// src/index.ts
|
|
1482
1120
|
import { useLiveQuery as useQuery } from "dexie-react-hooks";
|
|
1483
1121
|
export {
|
|
1484
|
-
BasicDBSDK,
|
|
1485
1122
|
BasicProvider,
|
|
1486
1123
|
useBasic,
|
|
1487
1124
|
useQuery
|