Skip to content

Commit b40182e

Browse files
authored
Merge pull request #151 from kinde-oss/docs/add-jsdoc
2 parents 263d9db + ffc1bf3 commit b40182e

File tree

6 files changed

+293
-1
lines changed

6 files changed

+293
-1
lines changed

lib/utils/isCustomDomain.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,37 @@
1+
/**
2+
* Checks if a domain is a custom domain (not a Kinde.com domain).
3+
*
4+
* This function determines whether the provided domain is a custom domain
5+
* by checking if it matches the pattern for Kinde.com domains. A domain
6+
* is considered custom if it does NOT match the Kinde.com pattern.
7+
*
8+
* The function accepts domains with or without protocol (http/https) and
9+
* checks against the pattern: `*.kinde.com` (case insensitive).
10+
*
11+
* @param domain - The domain string to check (can include protocol)
12+
* @returns True if the domain is a custom domain, false if it's a Kinde.com domain
13+
*
14+
* @example
15+
* ```typescript
16+
* isCustomDomain("https://app.kinde.com")
17+
* // Returns: false
18+
*
19+
* isCustomDomain("app.kinde.com")
20+
* // Returns: false
21+
*
22+
* isCustomDomain("https://myapp.com")
23+
* // Returns: true
24+
*
25+
* isCustomDomain("myapp.com")
26+
* // Returns: true
27+
*
28+
* isCustomDomain("https://auth.mycompany.com")
29+
* // Returns: true
30+
*
31+
* isCustomDomain("https://subdomain.kinde.com")
32+
* // Returns: false
33+
* ```
34+
*/
135
export const isCustomDomain = (domain: string): boolean => {
236
return !domain.match(
337
/^(?:https?:\/\/)?[a-zA-Z0-9][.-a-zA-Z0-9]*\.kinde\.com$/i,

lib/utils/navigateToKinde.ts

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,73 @@
1+
/**
2+
* Configuration options for popup window dimensions and position.
3+
*/
14
export type PopupOptions = {
5+
/** Width of the popup window in pixels (default: 500) */
26
width?: number;
7+
/** Height of the popup window in pixels (default: 600) */
38
height?: number;
9+
/** Left position of the popup window in pixels (default: centered) */
410
left?: number;
11+
/** Top position of the popup window in pixels (default: centered) */
512
top?: number;
613
};
714

15+
/**
16+
* Checks if the current window is running inside a popup.
17+
*
18+
* @returns True if the current window is a popup (self !== top), false otherwise
19+
*/
820
export const openInPopup = (): boolean => {
921
return window.self !== window.top;
1022
};
1123

24+
/**
25+
* Configuration options for navigating to Kinde authentication.
26+
*/
1227
export type NavigateToKindeOptions = {
28+
/** The URL to navigate to for authentication */
1329
url: string;
30+
/** Optional popup window configuration */
1431
popupOptions?: PopupOptions;
32+
/** Optional callback to handle authentication results */
1533
handleResult?: (result: URLSearchParams) => Promise<void>;
34+
/** Force popup window (default: false) */
1635
forcePopup?: boolean;
1736
};
1837

38+
/**
39+
* Navigates to Kinde authentication URL, either in a popup or by redirecting the current page.
40+
*
41+
* This function determines whether to open the authentication URL in a popup window
42+
* or redirect the current page based on the current context and options provided.
43+
* If the current window is in an iFrame a popup or forcePopup is true, it will create
44+
* a new popup window. Otherwise, it redirects the current page.
45+
*
46+
* @param options - Configuration options for the navigation
47+
* @returns A promise that resolves when navigation is complete
48+
*
49+
* @example
50+
* ```typescript
51+
* // Navigate to authentication in popup
52+
* await navigateToKinde({
53+
* url: "https://app.kinde.com/oauth/authorize?client_id=...",
54+
* popupOptions: { width: 600, height: 700 },
55+
* handleResult: async (result) => {
56+
* console.log("Auth result:", result);
57+
* // Handle authentication result
58+
* },
59+
* forcePopup: true
60+
* });
61+
*
62+
* // Navigate by redirecting current page
63+
* await navigateToKinde({
64+
* url: "https://app.kinde.com/oauth/authorize?client_id=...",
65+
* handleResult: async (result) => {
66+
* // This will only be called if in popup mode on completion
67+
* }
68+
* });
69+
* ```
70+
*/
1971
export const navigateToKinde = async ({
2072
url,
2173
popupOptions = {},
@@ -33,6 +85,34 @@ export const navigateToKinde = async ({
3385
}
3486
};
3587

88+
/**
89+
* Creates a popup window for Kinde authentication and waits for the result.
90+
*
91+
* This function opens a popup window with the specified URL and waits for
92+
* a message from the popup containing authentication results. The popup
93+
* window is configured with the provided options and positioned on screen.
94+
*
95+
* @param options - Configuration options for the popup
96+
* @returns A promise that resolves with the popup window reference, or null if blocked
97+
* @throws {Error} When the popup is blocked by the browser
98+
* @throws {Error} When authentication fails
99+
*
100+
* @example
101+
* ```typescript
102+
* const popup = await createPopup({
103+
* url: "https://app.kinde.com/oauth/authorize?client_id=...",
104+
* popupOptions: {
105+
* width: 600,
106+
* height: 700,
107+
* left: 100,
108+
* top: 100
109+
* },
110+
* handleResult: async (result) => {
111+
* console.log("Authentication completed:", result);
112+
* }
113+
* });
114+
* ```
115+
*/
36116
export const createPopup = async ({
37117
url,
38118
popupOptions = {},
@@ -82,6 +162,25 @@ export const createPopup = async ({
82162
return popup;
83163
};
84164

165+
/**
166+
* Waits for a popup window to close by polling its closed state.
167+
*
168+
* This function creates a promise that resolves when the specified popup window
169+
* is closed. It polls the popup's closed property every 100ms until the window
170+
* is no longer open.
171+
*
172+
* @param popup - The popup window to monitor
173+
* @returns A promise that resolves when the popup is closed
174+
*
175+
* @example
176+
* ```typescript
177+
* const popup = await createPopup({ url: "https://example.com" });
178+
*
179+
* // Wait for popup to close
180+
* await waitForPopupClose(popup);
181+
* console.log("Popup has been closed");
182+
* ```
183+
*/
85184
export const waitForPopupClose = (popup: Window): Promise<void> => {
86185
return new Promise((resolve) => {
87186
const checkClosed = () => {

lib/utils/refreshTimer.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
1+
/**
2+
* Global timer reference for managing refresh timers.
3+
* Used to store the timeout ID for the current refresh timer.
4+
*/
15
let refreshTimer: number | undefined;
26

7+
/**
8+
* Sets a refresh timer with automatic cleanup and safety constraints.
9+
*
10+
* This function creates a new timer that will execute the provided callback function.
11+
* It automatically clears any existing timer before setting a new one to prevent
12+
* multiple timers from running simultaneously. The timer duration is constrained
13+
* to prevent extremely long or short timers.
14+
*
15+
* The timer duration is automatically adjusted to be at least 10 seconds less than
16+
* the requested duration and capped at 24 hours (86400000ms) for safety.
17+
*
18+
* @param timer - The timer duration in seconds
19+
* @param callback - The function to execute when the timer expires
20+
* @throws {Error} When called outside of a browser environment
21+
* @throws {Error} When timer duration is not positive
22+
*
23+
* @example
24+
* ```typescript
25+
* // Set a timer for 60 seconds
26+
* setRefreshTimer(60, () => {
27+
* console.log("Timer expired!");
28+
* // Perform refresh logic here
29+
* });
30+
*
31+
* // Set a timer for 1 hour (3600 seconds)
32+
* setRefreshTimer(3600, () => {
33+
* // Refresh authentication token
34+
* refreshAuthToken();
35+
* });
36+
* ```
37+
*/
338
export function setRefreshTimer(timer: number, callback: () => void) {
439
clearRefreshTimer();
540
if (typeof window === "undefined") {
@@ -14,6 +49,24 @@ export function setRefreshTimer(timer: number, callback: () => void) {
1449
);
1550
}
1651

52+
/**
53+
* Clears the current refresh timer if one exists.
54+
*
55+
* This function safely clears any active refresh timer and resets the timer reference.
56+
* It's safe to call even if no timer is currently active.
57+
*
58+
* @example
59+
* ```typescript
60+
* // Clear any existing timer
61+
* clearRefreshTimer();
62+
*
63+
* // Set a new timer
64+
* setRefreshTimer(300, handleRefresh);
65+
*
66+
* // Later, clear it before it expires
67+
* clearRefreshTimer();
68+
* ```
69+
*/
1770
export function clearRefreshTimer() {
1871
if (refreshTimer !== undefined) {
1972
window.clearTimeout(refreshTimer);

lib/utils/sanitizeUrl.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
1-
//function to remove trailing slash
1+
/**
2+
* Removes trailing slashes from a URL string.
3+
*
4+
* This function uses a regular expression to remove any trailing forward slash
5+
* from the end of a URL string. It only removes the slash if it's at the very
6+
* end of the string, preserving any other slashes within the URL.
7+
*
8+
* @param url - The URL string to sanitize
9+
* @returns The URL string with trailing slash removed, or the original string if no trailing slash exists
10+
*
11+
* @example
12+
* ```typescript
13+
* sanitizeUrl("https://example.com/")
14+
* // Returns: "https://example.com"
15+
*
16+
* sanitizeUrl("https://example.com/api/v1/")
17+
* // Returns: "https://example.com/api/v1"
18+
*
19+
* sanitizeUrl("https://example.com")
20+
* // Returns: "https://example.com" (no change)
21+
*
22+
* sanitizeUrl("https://example.com/path/to/resource/")
23+
* // Returns: "https://example.com/path/to/resource"
24+
* ```
25+
*/
226
export const sanitizeUrl = (url: string): string => {
327
return url.replace(/\/$/, "");
428
};

lib/utils/snakeToCamelCase.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,62 @@
1+
/**
2+
* Recursively converts object keys from snake_case to camelCase.
3+
*
4+
* This function traverses an object (including nested objects and arrays) and converts
5+
* all property names from snake_case format to camelCase format. The function handles
6+
* nested objects, arrays, and primitive values appropriately.
7+
*
8+
* @template T - The expected return type (defaults to unknown)
9+
* @param obj - The object whose keys should be converted from snake_case to camelCase
10+
* @returns A new object with all keys converted to camelCase format
11+
*
12+
* @example
13+
* ```typescript
14+
* const input = {
15+
* user_name: "John",
16+
* user_details: {
17+
* first_name: "John",
18+
* last_name: "Doe",
19+
* contact_info: {
20+
* email_address: "john@example.com",
21+
* phone_number: "123-456-7890"
22+
* }
23+
* },
24+
* active_status: true
25+
* };
26+
*
27+
* const result = snakeToCamelCase(input);
28+
* // Returns:
29+
* // {
30+
* // userName: "John",
31+
* // userDetails: {
32+
* // firstName: "John",
33+
* // lastName: "Doe",
34+
* // contactInfo: {
35+
* // emailAddress: "john@example.com",
36+
* // phoneNumber: "123-456-7890"
37+
* // }
38+
* // },
39+
* // activeStatus: true
40+
* // }
41+
*
42+
* // With arrays
43+
* const arrayInput = {
44+
* user_list: [
45+
* { first_name: "John", last_name: "Doe" },
46+
* { first_name: "Jane", last_name: "Smith" }
47+
* ]
48+
* };
49+
*
50+
* const arrayResult = snakeToCamelCase(arrayInput);
51+
* // Returns:
52+
* // {
53+
* // userList: [
54+
* // { firstName: "John", lastName: "Doe" },
55+
* // { firstName: "Jane", lastName: "Smith" }
56+
* // ]
57+
* // }
58+
* ```
59+
*/
160
export const snakeToCamelCase = <T = unknown>(obj: object): T => {
261
if (typeof obj !== "object" || obj === null) return obj;
362

lib/utils/splitString.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
/**
2+
* Splits a string into an array of substrings, each with a maximum specified length.
3+
*
4+
* This function uses a regular expression to split the input string into chunks,
5+
* where each chunk has a maximum length specified by the `length` parameter.
6+
* If the length is less than or equal to 0, an empty array is returned.
7+
*
8+
* @param str - The string to be split into chunks
9+
* @param length - The maximum length of each chunk. Must be greater than 0
10+
* @returns An array of strings, where each string has a maximum length of `length`
11+
*
12+
* @example
13+
* ```typescript
14+
* splitString("Hello World", 3)
15+
* // Returns: ["Hel", "lo ", "Wor", "ld"]
16+
*
17+
* splitString("JavaScript", 5)
18+
* // Returns: ["JavaS", "cript"]
19+
*
20+
* splitString("Test", 0)
21+
* // Returns: []
22+
* ```
23+
*/
124
export function splitString(str: string, length: number): string[] {
225
if (length <= 0) {
326
return [];

0 commit comments

Comments
 (0)