Skip to content

Commit 4db1e58

Browse files
authored
feat(clerk-js): Introduce debugLogger (#6452)
1 parent 307dc3f commit 4db1e58

File tree

23 files changed

+1906
-46
lines changed

23 files changed

+1906
-46
lines changed

.changeset/all-cougars-hide.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@clerk/clerk-js': patch
3+
'@clerk/types': patch
4+
---
5+
6+
Introduce debugLogger for internal debugging support

.typedoc/__tests__/__snapshots__/file-structure.test.ts.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ exports[`Typedoc output > should have a deliberate file structure 1`] = `
125125
"types/sign-up-resource.mdx",
126126
"types/signed-in-session-resource.mdx",
127127
"types/state-selectors.mdx",
128+
"types/telemetry-log-entry.mdx",
128129
"types/use-auth-return.mdx",
129130
"types/use-session-list-return.mdx",
130131
"types/use-session-return.mdx",
@@ -148,6 +149,7 @@ exports[`Typedoc output > should have a deliberate file structure 1`] = `
148149
"shared/derive-state.mdx",
149150
"shared/extract-dev-browser-jwt-from-url.mdx",
150151
"shared/fast-deep-merge-and-replace.mdx",
152+
"shared/generate-uuid.mdx",
151153
"shared/get-clerk-js-major-version-or-tag.mdx",
152154
"shared/get-cookie-suffix.mdx",
153155
"shared/get-env-variable.mdx",

packages/clerk-js/bundlewatch.config.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"files": [
3-
{ "path": "./dist/clerk.js", "maxSize": "625KB" },
3+
{ "path": "./dist/clerk.js", "maxSize": "626KB" },
44
{ "path": "./dist/clerk.browser.js", "maxSize": "78KB" },
5-
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "117KB" },
5+
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "119KB" },
66
{ "path": "./dist/clerk.headless*.js", "maxSize": "61KB" },
7-
{ "path": "./dist/ui-common*.js", "maxSize": "113KB" },
7+
{ "path": "./dist/ui-common*.js", "maxSize": "114KB" },
88
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "118KB" },
9-
{ "path": "./dist/vendors*.js", "maxSize": "40.2KB" },
9+
{ "path": "./dist/vendors*.js", "maxSize": "41KB" },
1010
{ "path": "./dist/coinbase*.js", "maxSize": "38KB" },
1111
{ "path": "./dist/stripe-vendors*.js", "maxSize": "1KB" },
1212
{ "path": "./dist/createorganization*.js", "maxSize": "5KB" },

packages/clerk-js/src/core/clerk.ts

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ import type {
8484
Web3Provider,
8585
} from '@clerk/types';
8686

87+
import type { DebugLoggerInterface } from '@/utils/debug';
88+
import { debugLogger, initDebugLogger } from '@/utils/debug';
89+
8790
import type { MountComponentRenderer } from '../ui/Components';
8891
import {
8992
ALLOWED_PROTOCOLS,
@@ -159,6 +162,11 @@ type SetActiveHook = (intent?: 'sign-out') => void | Promise<void>;
159162

160163
export type ClerkCoreBroadcastChannelEvent = { type: 'signout' };
161164

165+
/**
166+
* Interface for the debug logger with all available logging methods
167+
*/
168+
// DebugLoggerInterface imported from '@/utils/debug'
169+
162170
declare global {
163171
interface Window {
164172
Clerk?: Clerk;
@@ -197,8 +205,8 @@ export class Clerk implements ClerkInterface {
197205
public static sdkMetadata: SDKMetadata = {
198206
name: __PKG_NAME__,
199207
version: __PKG_VERSION__,
200-
environment: process.env.NODE_ENV || 'production',
201208
};
209+
202210
private static _billing: CommerceBillingNamespace;
203211
private static _apiKeys: APIKeysNamespace;
204212
private _checkout: ClerkInterface['__experimental_checkout'] | undefined;
@@ -210,6 +218,8 @@ export class Clerk implements ClerkInterface {
210218
public __internal_country?: string | null;
211219
public telemetry: TelemetryCollector | undefined;
212220
public readonly __internal_state: State = new State();
221+
// Deprecated: use global singleton from `@/utils/debug`
222+
public debugLogger?: DebugLoggerInterface;
213223

214224
protected internal_last_error: ClerkAPIError | null = null;
215225
// converted to protected environment to support `updateEnvironment` type assertion
@@ -404,6 +414,7 @@ export class Clerk implements ClerkInterface {
404414
public getFapiClient = (): FapiClient => this.#fapiClient;
405415

406416
public load = async (options?: ClerkOptions): Promise<void> => {
417+
debugLogger.info('load() start', {}, 'clerk');
407418
if (this.loaded) {
408419
return;
409420
}
@@ -448,10 +459,18 @@ export class Clerk implements ClerkInterface {
448459
} else {
449460
await this.#loadInNonStandardBrowser();
450461
}
451-
} catch (e) {
462+
if (this.environment?.clientDebugMode) {
463+
initDebugLogger({
464+
enabled: true,
465+
telemetryCollector: this.telemetry,
466+
});
467+
}
468+
debugLogger.info('load() complete', {}, 'clerk');
469+
} catch (error) {
452470
this.#publicEventBus.emit(clerkEvents.Status, 'error');
471+
debugLogger.error('load() failed', { error }, 'clerk');
453472
// bubble up the error
454-
throw e;
473+
throw error;
455474
}
456475
};
457476

@@ -477,6 +496,16 @@ export class Clerk implements ClerkInterface {
477496
const opts = callbackOrOptions && typeof callbackOrOptions === 'object' ? callbackOrOptions : options || {};
478497

479498
const redirectUrl = opts?.redirectUrl || this.buildAfterSignOutUrl();
499+
debugLogger.debug(
500+
'signOut() start',
501+
{
502+
hasClient: Boolean(this.client),
503+
multiSessionCount: this.client?.signedInSessions.length ?? 0,
504+
redirectUrl,
505+
sessionTarget: opts?.sessionId ?? null,
506+
},
507+
'clerk',
508+
);
480509
const signOutCallback = typeof callbackOrOptions === 'function' ? callbackOrOptions : undefined;
481510

482511
const executeSignOut = async () => {
@@ -520,6 +549,7 @@ export class Clerk implements ClerkInterface {
520549

521550
await executeSignOut();
522551

552+
debugLogger.info('signOut() complete', { redirectUrl: stripOrigin(redirectUrl) }, 'clerk');
523553
return;
524554
}
525555

@@ -531,6 +561,7 @@ export class Clerk implements ClerkInterface {
531561

532562
if (shouldSignOutCurrent) {
533563
await executeSignOut();
564+
debugLogger.info('signOut() complete', { redirectUrl: stripOrigin(redirectUrl) }, 'clerk');
534565
}
535566
};
536567

@@ -1202,13 +1233,25 @@ export class Clerk implements ClerkInterface {
12021233
const { organization, beforeEmit, redirectUrl, navigate: setActiveNavigate } = params;
12031234
let { session } = params;
12041235
this.__internal_setActiveInProgress = true;
1205-
1236+
debugLogger.debug(
1237+
'setActive() start',
1238+
{
1239+
hasClient: Boolean(this.client),
1240+
sessionTarget: typeof session === 'string' ? session : (session?.id ?? session ?? null),
1241+
organizationTarget:
1242+
typeof organization === 'string' ? organization : (organization?.id ?? organization ?? null),
1243+
redirectUrl: redirectUrl ?? null,
1244+
},
1245+
'clerk',
1246+
);
12061247
try {
12071248
if (!this.client) {
1249+
debugLogger.warn('Clerk setActive called before client is loaded', {}, 'clerk');
12081250
throw new Error('setActive is being called before the client is loaded. Wait for init.');
12091251
}
12101252

12111253
if (session === undefined && !this.session) {
1254+
debugLogger.warn('Clerk setActive precondition not met: no target session and no active session', {}, 'clerk');
12121255
throw new Error(
12131256
'setActive should either be called with a session param or there should be already an active session.',
12141257
);
@@ -1414,6 +1457,7 @@ export class Clerk implements ClerkInterface {
14141457
const customNavigate =
14151458
options?.replace && this.#options.routerReplace ? this.#options.routerReplace : this.#options.routerPush;
14161459

1460+
debugLogger.info(`Clerk is navigating to: ${toURL}`);
14171461
if (this.#options.routerDebug) {
14181462
console.log(`Clerk is navigating to: ${toURL}`);
14191463
}

packages/clerk-js/src/core/fapiClient.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { retry } from '@clerk/shared/retry';
33
import { camelToSnake } from '@clerk/shared/underscore';
44
import type { ClerkAPIErrorJSON, ClientJSON, InstanceType } from '@clerk/types';
55

6+
import { debugLogger } from '@/utils/debug';
7+
68
import { buildEmailAddress as buildEmailAddressUtil, buildURL as buildUrlUtil, stringifyQueryParams } from '../utils';
79
import { SUPPORTED_FAPI_VERSION } from './constants';
810
import { clerkNetworkError } from './errors';
@@ -250,12 +252,16 @@ export function createFapiClient(options: FapiClientOptions): FapiClient {
250252
response = new Response('{}', requestInit); // Mock an empty json response
251253
}
252254
} catch (e) {
255+
debugLogger.error('network error', { error: e, url: urlStr, method }, 'fapiClient');
253256
clerkNetworkError(urlStr, e);
254257
}
255258

256259
// 204 No Content responses do not have a body so we should not try to parse it
257260
const json: FapiResponseJSON<T> | null = response.status !== 204 ? await response.json() : null;
258261
const fapiResponse: FapiResponse<T> = Object.assign(response, { payload: json });
262+
if (!response.ok) {
263+
debugLogger.error('request failed', { method, path: requestInit.path, status: response.status }, 'fapiClient');
264+
}
259265
await runAfterResponseCallbacks(requestInit, fapiResponse);
260266
return fapiResponse;
261267
}

0 commit comments

Comments
 (0)