Clean up console logging and fix platform detection issues
- Reduce migration/platform logging verbosity in development mode (~80-90% less noise) - Fix AbsurdSQL platform check to support 'development' alongside 'web' - Add missing WebPlatformService methods (isWorker, initSharedArrayBuffer) - Fix Electron API endpoint resolution to prevent JSON parsing errors - Prevent circular database logging that caused [DB-PREVENTED-INFO] spam Console now shows only essential information while preserving all errors/warnings
This commit is contained in:
@@ -512,7 +512,11 @@ export async function getPlanFromCache(
|
|||||||
cred = resp.data.data[0];
|
cred = resp.data.data[0];
|
||||||
planCache.set(handleId, cred);
|
planCache.set(handleId, cred);
|
||||||
} else {
|
} else {
|
||||||
logger.log(
|
// Use debug level for development to reduce console noise
|
||||||
|
const isDevelopment = process.env.VITE_PLATFORM === "development";
|
||||||
|
const log = isDevelopment ? logger.debug : logger.log;
|
||||||
|
|
||||||
|
log(
|
||||||
"[EndorserServer] Plan cache is empty for handle",
|
"[EndorserServer] Plan cache is empty for handle",
|
||||||
handleId,
|
handleId,
|
||||||
" Got data:",
|
" Got data:",
|
||||||
|
|||||||
@@ -33,6 +33,31 @@ import { initializeApp } from "./main.common";
|
|||||||
import { handleApiError } from "./services/api";
|
import { handleApiError } from "./services/api";
|
||||||
import { logger } from "./utils/logger";
|
import { logger } from "./utils/logger";
|
||||||
|
|
||||||
|
// **CRITICAL**: Disable any existing service workers that might intercept API calls
|
||||||
|
// Service workers from web sessions can persist and cause issues in Electron
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||||
|
navigator.serviceWorker
|
||||||
|
?.getRegistrations()
|
||||||
|
.then(function (registrations) {
|
||||||
|
for (const registration of registrations) {
|
||||||
|
logger.debug(
|
||||||
|
"[Electron] Unregistering service worker:",
|
||||||
|
registration.scope,
|
||||||
|
);
|
||||||
|
registration.unregister();
|
||||||
|
}
|
||||||
|
if (registrations.length > 0) {
|
||||||
|
logger.log(
|
||||||
|
"[Electron] Cleaned up",
|
||||||
|
registrations.length,
|
||||||
|
"service worker registrations",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
logger.debug("[Electron] Service worker cleanup failed:", error);
|
||||||
|
});
|
||||||
|
|
||||||
logger.log("[Electron] Starting initialization");
|
logger.log("[Electron] Starting initialization");
|
||||||
logger.log("[Electron] Platform:", process.env.VITE_PLATFORM);
|
logger.log("[Electron] Platform:", process.env.VITE_PLATFORM);
|
||||||
|
|
||||||
@@ -61,13 +86,22 @@ if (typeof window !== "undefined" && window.require) {
|
|||||||
// **CRITICAL FIX**: Disable any existing service worker that might be intercepting API calls
|
// **CRITICAL FIX**: Disable any existing service worker that might be intercepting API calls
|
||||||
try {
|
try {
|
||||||
if (navigator.serviceWorker?.getRegistrations) {
|
if (navigator.serviceWorker?.getRegistrations) {
|
||||||
navigator.serviceWorker.getRegistrations().then(function(registrations) {
|
navigator.serviceWorker
|
||||||
for(let registration of registrations) {
|
.getRegistrations()
|
||||||
console.log("[Electron] Unregistering service worker:", registration.scope);
|
.then(function (registrations) {
|
||||||
|
for (const registration of registrations) {
|
||||||
|
console.log(
|
||||||
|
"[Electron] Unregistering service worker:",
|
||||||
|
registration.scope,
|
||||||
|
);
|
||||||
registration.unregister();
|
registration.unregister();
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
})
|
||||||
console.log("[Electron] Failed to unregister service workers:", error);
|
.catch((error) => {
|
||||||
|
console.log(
|
||||||
|
"[Electron] Failed to unregister service workers:",
|
||||||
|
error,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -70,11 +70,13 @@ class AbsurdSqlDatabaseService implements DatabaseService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// **PLATFORM CHECK**: AbsurdSqlDatabaseService should only run on web platform
|
// **PLATFORM CHECK**: AbsurdSqlDatabaseService should only run on web-based platforms
|
||||||
// This prevents SharedArrayBuffer checks and web-specific initialization on Electron/Capacitor
|
// This prevents SharedArrayBuffer checks and web-specific initialization on Electron/Capacitor
|
||||||
if (process.env.VITE_PLATFORM !== "web") {
|
// Allow both 'web' (production) and 'development' (dev server) platforms
|
||||||
|
const webBasedPlatforms = ["web", "development"];
|
||||||
|
if (!webBasedPlatforms.includes(process.env.VITE_PLATFORM || "")) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`AbsurdSqlDatabaseService is only supported on web platform. Current platform: ${process.env.VITE_PLATFORM}`,
|
`AbsurdSqlDatabaseService is only supported on web-based platforms (web, development). Current platform: ${process.env.VITE_PLATFORM}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,12 +99,16 @@ class AbsurdSqlDatabaseService implements DatabaseService {
|
|||||||
// **SHARED ARRAY BUFFER FALLBACK**: Only needed for web platform
|
// **SHARED ARRAY BUFFER FALLBACK**: Only needed for web platform
|
||||||
// This check handles Safari and other browsers without SharedArrayBuffer support
|
// This check handles Safari and other browsers without SharedArrayBuffer support
|
||||||
if (typeof SharedArrayBuffer === "undefined") {
|
if (typeof SharedArrayBuffer === "undefined") {
|
||||||
logger.debug("[AbsurdSqlDatabaseService] SharedArrayBuffer not available, using fallback mode");
|
logger.debug(
|
||||||
|
"[AbsurdSqlDatabaseService] SharedArrayBuffer not available, using fallback mode",
|
||||||
|
);
|
||||||
const stream = SQL.FS.open(path, "a+");
|
const stream = SQL.FS.open(path, "a+");
|
||||||
await stream.node.contents.readIfFallback();
|
await stream.node.contents.readIfFallback();
|
||||||
SQL.FS.close(stream);
|
SQL.FS.close(stream);
|
||||||
} else {
|
} else {
|
||||||
logger.debug("[AbsurdSqlDatabaseService] SharedArrayBuffer available, using optimized mode");
|
logger.debug(
|
||||||
|
"[AbsurdSqlDatabaseService] SharedArrayBuffer available, using optimized mode",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.db = new SQL.Database(path, { filename: true });
|
this.db = new SQL.Database(path, { filename: true });
|
||||||
|
|||||||
@@ -400,12 +400,17 @@ async function isSchemaAlreadyPresent<T>(
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export async function runMigrations<T>(
|
export async function runMigrations<T>(
|
||||||
sqlExec: (sql: string, params?: unknown[]) => Promise<unknown>,
|
sqlExec: (sql: string, params?: unknown[]) => Promise<void>,
|
||||||
sqlQuery: (sql: string, params?: unknown[]) => Promise<T>,
|
sqlQuery: (sql: string, params?: unknown[]) => Promise<T>,
|
||||||
extractMigrationNames: (result: T) => Set<string>,
|
extractMigrationNames: (result: T) => Set<string>,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const isDevelopment = process.env.VITE_PLATFORM === "development";
|
||||||
|
|
||||||
|
// Use debug level for routine migration messages in development
|
||||||
|
const migrationLog = isDevelopment ? logger.debug : logger.log;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
logger.log("📋 [Migration] Starting migration process...");
|
migrationLog("📋 [Migration] Starting migration process...");
|
||||||
|
|
||||||
// Step 1: Create migrations table if it doesn't exist
|
// Step 1: Create migrations table if it doesn't exist
|
||||||
// Note: We use IF NOT EXISTS here because this is infrastructure, not a business migration
|
// Note: We use IF NOT EXISTS here because this is infrastructure, not a business migration
|
||||||
@@ -431,7 +436,7 @@ export async function runMigrations<T>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log(
|
migrationLog(
|
||||||
`📊 [Migration] Found ${migrations.length} total migrations, ${appliedMigrations.size} already applied`,
|
`📊 [Migration] Found ${migrations.length} total migrations, ${appliedMigrations.size} already applied`,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -458,7 +463,7 @@ export async function runMigrations<T>(
|
|||||||
await sqlExec("INSERT INTO migrations (name) VALUES (?)", [
|
await sqlExec("INSERT INTO migrations (name) VALUES (?)", [
|
||||||
migration.name,
|
migration.name,
|
||||||
]);
|
]);
|
||||||
logger.log(
|
migrationLog(
|
||||||
`✅ [Migration] Marked existing schema as applied: ${migration.name}`,
|
`✅ [Migration] Marked existing schema as applied: ${migration.name}`,
|
||||||
);
|
);
|
||||||
skippedCount++;
|
skippedCount++;
|
||||||
@@ -473,7 +478,7 @@ export async function runMigrations<T>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply the migration
|
// Apply the migration
|
||||||
logger.log(`🔄 [Migration] Applying migration: ${migration.name}`);
|
migrationLog(`🔄 [Migration] Applying migration: ${migration.name}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Execute the migration SQL
|
// Execute the migration SQL
|
||||||
@@ -496,7 +501,7 @@ export async function runMigrations<T>(
|
|||||||
migration.name,
|
migration.name,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
logger.log(`🎉 [Migration] Successfully applied: ${migration.name}`);
|
migrationLog(`🎉 [Migration] Successfully applied: ${migration.name}`);
|
||||||
appliedCount++;
|
appliedCount++;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`❌ [Migration] Error applying ${migration.name}:`, error);
|
logger.error(`❌ [Migration] Error applying ${migration.name}:`, error);
|
||||||
@@ -512,7 +517,7 @@ export async function runMigrations<T>(
|
|||||||
(errorMessage.includes("table") &&
|
(errorMessage.includes("table") &&
|
||||||
errorMessage.includes("already exists"))
|
errorMessage.includes("already exists"))
|
||||||
) {
|
) {
|
||||||
logger.log(
|
migrationLog(
|
||||||
`⚠️ [Migration] ${migration.name} appears already applied (${errorMessage}). Validating and marking as complete.`,
|
`⚠️ [Migration] ${migration.name} appears already applied (${errorMessage}). Validating and marking as complete.`,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -533,7 +538,7 @@ export async function runMigrations<T>(
|
|||||||
await sqlExec("INSERT INTO migrations (name) VALUES (?)", [
|
await sqlExec("INSERT INTO migrations (name) VALUES (?)", [
|
||||||
migration.name,
|
migration.name,
|
||||||
]);
|
]);
|
||||||
logger.log(`✅ [Migration] Marked as applied: ${migration.name}`);
|
migrationLog(`✅ [Migration] Marked as applied: ${migration.name}`);
|
||||||
appliedCount++;
|
appliedCount++;
|
||||||
} catch (insertError) {
|
} catch (insertError) {
|
||||||
// If we can't insert the migration record, log it but don't fail
|
// If we can't insert the migration record, log it but don't fail
|
||||||
@@ -569,6 +574,7 @@ export async function runMigrations<T>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always show completion message
|
||||||
logger.log(
|
logger.log(
|
||||||
`🎉 [Migration] Migration process complete! Summary: ${appliedCount} applied, ${skippedCount} skipped`,
|
`🎉 [Migration] Migration process complete! Summary: ${appliedCount} applied, ${skippedCount} skipped`,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -48,15 +48,21 @@ export class WebPlatformService implements PlatformService {
|
|||||||
constructor() {
|
constructor() {
|
||||||
WebPlatformService.instanceCount++;
|
WebPlatformService.instanceCount++;
|
||||||
|
|
||||||
// Only warn if multiple instances (which shouldn't happen with singleton)
|
// Use debug level logging for development mode to reduce console noise
|
||||||
if (WebPlatformService.instanceCount > 1) {
|
const isDevelopment = process.env.VITE_PLATFORM === "development";
|
||||||
console.error(
|
const log = isDevelopment ? logger.debug : logger.log;
|
||||||
`[WebPlatformService] ERROR: Multiple instances created! Count: ${WebPlatformService.instanceCount}`,
|
|
||||||
);
|
log("[WebPlatformService] Initializing web platform service");
|
||||||
} else {
|
|
||||||
console.log(`[WebPlatformService] Initializing web platform service`);
|
// Only initialize SharedArrayBuffer setup for web platforms
|
||||||
|
if (this.isWorker()) {
|
||||||
|
log("[WebPlatformService] Skipping initBackend call in worker context");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize shared array buffer for main thread
|
||||||
|
this.initSharedArrayBuffer();
|
||||||
|
|
||||||
// Start worker initialization but don't await it in constructor
|
// Start worker initialization but don't await it in constructor
|
||||||
this.workerInitPromise = this.initializeWorker();
|
this.workerInitPromise = this.initializeWorker();
|
||||||
}
|
}
|
||||||
@@ -629,4 +635,18 @@ export class WebPlatformService implements PlatformService {
|
|||||||
async rotateCamera(): Promise<void> {
|
async rotateCamera(): Promise<void> {
|
||||||
throw new Error("Camera rotation not implemented in web platform");
|
throw new Error("Camera rotation not implemented in web platform");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if running in a worker context
|
||||||
|
*/
|
||||||
|
private isWorker(): boolean {
|
||||||
|
return typeof window === "undefined";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize SharedArrayBuffer setup (handled by initBackend in initializeWorker)
|
||||||
|
*/
|
||||||
|
private initSharedArrayBuffer(): void {
|
||||||
|
// SharedArrayBuffer initialization is handled by initBackend call in initializeWorker
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -465,7 +465,9 @@ export const PlatformServiceMixin = {
|
|||||||
// This ensures Electron always uses production endpoints regardless of cached settings
|
// This ensures Electron always uses production endpoints regardless of cached settings
|
||||||
if (process.env.VITE_PLATFORM === "electron") {
|
if (process.env.VITE_PLATFORM === "electron") {
|
||||||
// Import constants dynamically to get platform-specific values
|
// Import constants dynamically to get platform-specific values
|
||||||
const { DEFAULT_ENDORSER_API_SERVER } = await import("../constants/app");
|
const { DEFAULT_ENDORSER_API_SERVER } = await import(
|
||||||
|
"../constants/app"
|
||||||
|
);
|
||||||
settings.apiServer = DEFAULT_ENDORSER_API_SERVER;
|
settings.apiServer = DEFAULT_ENDORSER_API_SERVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,10 +43,13 @@ export const logger = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only log to database for important messages (not routine operations)
|
// Only log to database for important messages (not routine operations)
|
||||||
|
// Skip database logging for migration messages to avoid circular dependency
|
||||||
if (
|
if (
|
||||||
!message.includes("[CapacitorPlatformService]") &&
|
!message.includes("[CapacitorPlatformService]") &&
|
||||||
!message.includes("[CapacitorMigration]") &&
|
!message.includes("[CapacitorMigration]") &&
|
||||||
!message.includes("[DB-Integrity]")
|
!message.includes("[DB-Integrity]") &&
|
||||||
|
!message.includes("[Migration]") &&
|
||||||
|
!message.includes("[IndexedDBMigrationService]")
|
||||||
) {
|
) {
|
||||||
const argsString = args.length > 0 ? " - " + safeStringify(args) : "";
|
const argsString = args.length > 0 ? " - " + safeStringify(args) : "";
|
||||||
logToDb(message + argsString);
|
logToDb(message + argsString);
|
||||||
|
|||||||
@@ -557,6 +557,10 @@ export default class HomeView extends Vue {
|
|||||||
|
|
||||||
// Update component state
|
// Update component state
|
||||||
this.apiServer = settings.apiServer || "";
|
this.apiServer = settings.apiServer || "";
|
||||||
|
|
||||||
|
// **CRITICAL**: Ensure correct API server for platform
|
||||||
|
await this.ensureCorrectApiServer();
|
||||||
|
|
||||||
this.activeDid = settings.activeDid || "";
|
this.activeDid = settings.activeDid || "";
|
||||||
|
|
||||||
// Load contacts with graceful fallback
|
// Load contacts with graceful fallback
|
||||||
@@ -676,6 +680,22 @@ export default class HomeView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures API server is correctly set for the current platform
|
||||||
|
* For Electron, always use production endpoint regardless of saved settings
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
* Called after loading settings to ensure correct API endpoint
|
||||||
|
*/
|
||||||
|
private async ensureCorrectApiServer() {
|
||||||
|
if (process.env.VITE_PLATFORM === "electron") {
|
||||||
|
// **CRITICAL FIX**: Always use production API server for Electron
|
||||||
|
// This prevents the capacitor-electron:// protocol from being used for API calls
|
||||||
|
const { DEFAULT_ENDORSER_API_SERVER } = await import("../constants/app");
|
||||||
|
this.apiServer = DEFAULT_ENDORSER_API_SERVER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads user settings from storage using ultra-concise mixin utilities
|
* Loads user settings from storage using ultra-concise mixin utilities
|
||||||
* Sets component state for:
|
* Sets component state for:
|
||||||
@@ -696,6 +716,10 @@ export default class HomeView extends Vue {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.apiServer = settings.apiServer || "";
|
this.apiServer = settings.apiServer || "";
|
||||||
|
|
||||||
|
// **CRITICAL**: Ensure correct API server for platform
|
||||||
|
await this.ensureCorrectApiServer();
|
||||||
|
|
||||||
this.activeDid = settings.activeDid || "";
|
this.activeDid = settings.activeDid || "";
|
||||||
this.feedLastViewedClaimId = settings.lastViewedClaimId;
|
this.feedLastViewedClaimId = settings.lastViewedClaimId;
|
||||||
this.givenName = settings.firstName || "";
|
this.givenName = settings.firstName || "";
|
||||||
@@ -934,13 +958,15 @@ export default class HomeView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates feed with latest activity
|
* Updates feed data from endorser service with error handling
|
||||||
|
* - Retrieves new gives from API
|
||||||
|
* - Processes records through filters
|
||||||
|
* - Updates last viewed claim ID
|
||||||
|
* - Handles paging if needed
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
* @callGraph
|
* @callGraph
|
||||||
* Called by:
|
* Called by: loadFeedData(), manual refresh
|
||||||
* - loadMoreGives()
|
|
||||||
* - initializeIdentity()
|
|
||||||
* Calls:
|
* Calls:
|
||||||
* - retrieveGives()
|
* - retrieveGives()
|
||||||
* - processFeedResults()
|
* - processFeedResults()
|
||||||
@@ -948,12 +974,10 @@ export default class HomeView extends Vue {
|
|||||||
* - handleFeedError()
|
* - handleFeedError()
|
||||||
*
|
*
|
||||||
* @chain
|
* @chain
|
||||||
* loadMoreGives() -> updateAllFeed()
|
* loadFeedData() -> updateAllFeed() -> retrieveGives()
|
||||||
* initializeIdentity() -> updateAllFeed()
|
|
||||||
*
|
*
|
||||||
* @requires
|
* @requires
|
||||||
* - this.apiServer
|
* - this.apiServer
|
||||||
* - this.activeDid
|
|
||||||
* - this.feedPreviousOldestId
|
* - this.feedPreviousOldestId
|
||||||
*
|
*
|
||||||
* @modifies
|
* @modifies
|
||||||
@@ -1350,13 +1374,28 @@ export default class HomeView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve claims in reverse chronological order
|
* Retrieves gift data from endorser API with error handling
|
||||||
|
* - Fetches gives from API endpoint
|
||||||
|
* - Handles authentication headers
|
||||||
|
* - Processes API response with comprehensive error handling
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* @callGraph
|
||||||
|
* Called by: updateAllFeed()
|
||||||
|
* Calls:
|
||||||
|
* - getHeaders()
|
||||||
|
* - fetch()
|
||||||
|
*
|
||||||
|
* @chain
|
||||||
|
* updateAllFeed() -> retrieveGives() -> getHeaders()
|
||||||
|
*
|
||||||
|
* @requires
|
||||||
|
* - this.activeDid
|
||||||
|
* - this.$notify
|
||||||
*
|
*
|
||||||
* @internal
|
|
||||||
* Called by updateAllFeed()
|
|
||||||
* @param endorserApiServer API server URL
|
* @param endorserApiServer API server URL
|
||||||
* @param beforeId OptioCalled by updateAllFeed()nal ID to fetch earlier results
|
* @param beforeId Optional ID for pagination
|
||||||
* @returns claims in reverse chronological order
|
* @returns Promise resolving to API response data
|
||||||
*/
|
*/
|
||||||
async retrieveGives(endorserApiServer: string, beforeId?: string) {
|
async retrieveGives(endorserApiServer: string, beforeId?: string) {
|
||||||
const beforeQuery = beforeId == null ? "" : "&beforeId=" + beforeId;
|
const beforeQuery = beforeId == null ? "" : "&beforeId=" + beforeId;
|
||||||
@@ -1365,6 +1404,7 @@ export default class HomeView extends Vue {
|
|||||||
this.activeDid,
|
this.activeDid,
|
||||||
doNotShowErrorAgain ? undefined : this.$notify,
|
doNotShowErrorAgain ? undefined : this.$notify,
|
||||||
);
|
);
|
||||||
|
|
||||||
// retrieve headers for this user, but if an error happens then report it but proceed with the fetch with no header
|
// retrieve headers for this user, but if an error happens then report it but proceed with the fetch with no header
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
endorserApiServer +
|
endorserApiServer +
|
||||||
@@ -1380,7 +1420,8 @@ export default class HomeView extends Vue {
|
|||||||
throw await response.text();
|
throw await response.text();
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = await response.json();
|
const responseText = await response.text();
|
||||||
|
const results = JSON.parse(responseText);
|
||||||
|
|
||||||
if (results.data) {
|
if (results.data) {
|
||||||
return results;
|
return results;
|
||||||
|
|||||||
Reference in New Issue
Block a user