@authowl/react 0.21.1 → 0.22.0
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/dist/{TeamsSection-SHXAL64Q.js → TeamsSection-ZQDNMWV3.js} +1 -1
- package/dist/captcha-loader-VNULARCZ.js +68 -0
- package/dist/captcha-providers-STYFL25P.js +71 -0
- package/dist/{chunk-K67DJJHP.js → chunk-PUJV7S6G.js} +9 -6
- package/dist/index.cjs +1108 -926
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +872 -849
- package/package.json +2 -2
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/components/captcha-loader.ts
|
|
4
|
+
var SCRIPT_LOAD_TIMEOUT_MS = 1e4;
|
|
5
|
+
var GLOBAL_POLL_INTERVAL_MS = 25;
|
|
6
|
+
var loaders = /* @__PURE__ */ new Map();
|
|
7
|
+
function providerGlobal(adapter) {
|
|
8
|
+
const api = window[adapter.globalName];
|
|
9
|
+
return typeof api?.render === "function" ? api : void 0;
|
|
10
|
+
}
|
|
11
|
+
function loadCaptcha(adapter) {
|
|
12
|
+
const available = providerGlobal(adapter);
|
|
13
|
+
if (available) return Promise.resolve(available);
|
|
14
|
+
const cached = loaders.get(adapter.scriptUrl);
|
|
15
|
+
if (cached) return cached;
|
|
16
|
+
const loading = new Promise((resolve, reject) => {
|
|
17
|
+
const existing = document.querySelector(
|
|
18
|
+
`script[src="${adapter.scriptUrl}"]`
|
|
19
|
+
);
|
|
20
|
+
const script = existing ?? document.createElement("script");
|
|
21
|
+
let poll;
|
|
22
|
+
const cleanup = () => {
|
|
23
|
+
clearTimeout(timeout);
|
|
24
|
+
if (poll !== void 0) clearInterval(poll);
|
|
25
|
+
script.removeEventListener("load", loaded);
|
|
26
|
+
script.removeEventListener("error", failed);
|
|
27
|
+
};
|
|
28
|
+
const resolveWhenPublished = () => {
|
|
29
|
+
const api = providerGlobal(adapter);
|
|
30
|
+
if (!api) return false;
|
|
31
|
+
cleanup();
|
|
32
|
+
resolve(api);
|
|
33
|
+
return true;
|
|
34
|
+
};
|
|
35
|
+
const loaded = () => {
|
|
36
|
+
if (!resolveWhenPublished() && poll === void 0) {
|
|
37
|
+
poll = setInterval(resolveWhenPublished, GLOBAL_POLL_INTERVAL_MS);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const failed = () => {
|
|
41
|
+
cleanup();
|
|
42
|
+
if (!existing) script.remove();
|
|
43
|
+
reject(new Error(`${adapter.label} failed to load`));
|
|
44
|
+
};
|
|
45
|
+
const timeout = setTimeout(failed, SCRIPT_LOAD_TIMEOUT_MS);
|
|
46
|
+
script.addEventListener("load", loaded, { once: true });
|
|
47
|
+
script.addEventListener("error", failed, { once: true });
|
|
48
|
+
if (existing) {
|
|
49
|
+
loaded();
|
|
50
|
+
} else {
|
|
51
|
+
script.src = adapter.scriptUrl;
|
|
52
|
+
script.async = true;
|
|
53
|
+
script.defer = true;
|
|
54
|
+
const nonce = document.querySelector("script[nonce]")?.nonce;
|
|
55
|
+
if (nonce) script.nonce = nonce;
|
|
56
|
+
document.head.appendChild(script);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
const retryable = loading.catch((error) => {
|
|
60
|
+
loaders.delete(adapter.scriptUrl);
|
|
61
|
+
throw error;
|
|
62
|
+
});
|
|
63
|
+
loaders.set(adapter.scriptUrl, retryable);
|
|
64
|
+
return retryable;
|
|
65
|
+
}
|
|
66
|
+
export {
|
|
67
|
+
loadCaptcha
|
|
68
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/components/captcha-providers.ts
|
|
4
|
+
function preferredTheme() {
|
|
5
|
+
return typeof window !== "undefined" && window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
6
|
+
}
|
|
7
|
+
function teardown(api, widgetId) {
|
|
8
|
+
if (api.remove) {
|
|
9
|
+
try {
|
|
10
|
+
api.remove(widgetId);
|
|
11
|
+
return;
|
|
12
|
+
} catch {
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
api.reset?.(widgetId);
|
|
17
|
+
} catch {
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
var CAPTCHA_ADAPTERS = {
|
|
21
|
+
turnstile: {
|
|
22
|
+
scriptUrl: "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit",
|
|
23
|
+
globalName: "turnstile",
|
|
24
|
+
label: "Cloudflare Turnstile",
|
|
25
|
+
invisibleRenderOptions: ({ siteKey, theme, action, language }) => ({
|
|
26
|
+
sitekey: siteKey,
|
|
27
|
+
theme,
|
|
28
|
+
action,
|
|
29
|
+
language,
|
|
30
|
+
execution: "execute",
|
|
31
|
+
appearance: "interaction-only",
|
|
32
|
+
size: "flexible"
|
|
33
|
+
}),
|
|
34
|
+
teardown
|
|
35
|
+
},
|
|
36
|
+
hcaptcha: {
|
|
37
|
+
scriptUrl: "https://js.hcaptcha.com/1/api.js?render=explicit",
|
|
38
|
+
globalName: "hcaptcha",
|
|
39
|
+
label: "hCaptcha",
|
|
40
|
+
invisibleRenderOptions: ({ siteKey, theme }) => ({
|
|
41
|
+
sitekey: siteKey,
|
|
42
|
+
// 'auto' is Turnstile vocabulary. hCaptcha and reCAPTCHA take light|dark
|
|
43
|
+
// only and silently fall back to light on anything else, which reads badly
|
|
44
|
+
// in a dark application.
|
|
45
|
+
theme: theme === "auto" ? preferredTheme() : theme,
|
|
46
|
+
size: "invisible"
|
|
47
|
+
}),
|
|
48
|
+
teardown
|
|
49
|
+
},
|
|
50
|
+
"recaptcha-v2": {
|
|
51
|
+
scriptUrl: "https://www.google.com/recaptcha/api.js?render=explicit",
|
|
52
|
+
globalName: "grecaptcha",
|
|
53
|
+
label: "reCAPTCHA",
|
|
54
|
+
invisibleRenderOptions: ({ siteKey, theme }) => ({
|
|
55
|
+
sitekey: siteKey,
|
|
56
|
+
// 'auto' is Turnstile vocabulary. hCaptcha and reCAPTCHA take light|dark
|
|
57
|
+
// only and silently fall back to light on anything else, which reads badly
|
|
58
|
+
// in a dark application.
|
|
59
|
+
theme: theme === "auto" ? preferredTheme() : theme,
|
|
60
|
+
size: "invisible"
|
|
61
|
+
}),
|
|
62
|
+
teardown
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
function captchaAdapterFor(provider) {
|
|
66
|
+
return CAPTCHA_ADAPTERS[provider] ?? null;
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
CAPTCHA_ADAPTERS,
|
|
70
|
+
captchaAdapterFor
|
|
71
|
+
};
|
|
@@ -381,7 +381,7 @@ function warnPublicConfigFailed(resolved, error) {
|
|
|
381
381
|
warnedConfigProjects.add(key);
|
|
382
382
|
const reason = error instanceof Error ? error.message : String(error);
|
|
383
383
|
console.warn(
|
|
384
|
-
`[AuthOwl] Could not load this project's public config from ${origin} (${reason}).
|
|
384
|
+
`[AuthOwl] Could not load this project's public config from ${origin} (${reason}). Authentication UI is unavailable until the request succeeds. Likely causes: the API is unreachable, \`apiUrl\` is wrong, or the publishable key points at a missing/mismatched project. Check \`apiUrl\` and \`publishableKey\` on <AuthOwlProvider>. (This warning is dev-only.)`
|
|
385
385
|
);
|
|
386
386
|
}
|
|
387
387
|
var Context = React4.createContext(null);
|
|
@@ -418,6 +418,8 @@ function AuthOwlProvider({
|
|
|
418
418
|
const client = React4.useMemo(() => createAuthOwlClient(resolved), [resolved]);
|
|
419
419
|
const [config, setConfig] = React4.useState(null);
|
|
420
420
|
const [configState, setConfigState] = React4.useState("loading");
|
|
421
|
+
const [configAttempt, setConfigAttempt] = React4.useState(0);
|
|
422
|
+
const retryPublicConfig = React4.useCallback(() => setConfigAttempt((attempt) => attempt + 1), []);
|
|
421
423
|
React4.useEffect(() => {
|
|
422
424
|
let active = true;
|
|
423
425
|
setConfigState("loading");
|
|
@@ -434,7 +436,7 @@ function AuthOwlProvider({
|
|
|
434
436
|
return () => {
|
|
435
437
|
active = false;
|
|
436
438
|
};
|
|
437
|
-
}, [resolved]);
|
|
439
|
+
}, [resolved, configAttempt]);
|
|
438
440
|
const merged = resolveAppearance(appearance, config);
|
|
439
441
|
const [autoLocale, setAutoLocale] = React4.useState(null);
|
|
440
442
|
React4.useEffect(() => {
|
|
@@ -445,8 +447,8 @@ function AuthOwlProvider({
|
|
|
445
447
|
captureInvitationClaim();
|
|
446
448
|
}, []);
|
|
447
449
|
const ctxValue = React4.useMemo(
|
|
448
|
-
() => ({ client, appearance, config, configState, locale }),
|
|
449
|
-
[client, appearance, config, configState, locale]
|
|
450
|
+
() => ({ client, appearance, config, configState, retryPublicConfig, locale }),
|
|
451
|
+
[client, appearance, config, configState, retryPublicConfig, locale]
|
|
450
452
|
);
|
|
451
453
|
return /* @__PURE__ */ jsx4(Context.Provider, { value: ctxValue, children: /* @__PURE__ */ jsxs3(
|
|
452
454
|
"div",
|
|
@@ -489,11 +491,12 @@ function useAccount() {
|
|
|
489
491
|
return useAuthClient().account;
|
|
490
492
|
}
|
|
491
493
|
function usePublicConfig() {
|
|
492
|
-
const { config, configState } = useAuthOwlContext();
|
|
494
|
+
const { config, configState, retryPublicConfig } = useAuthOwlContext();
|
|
493
495
|
return {
|
|
494
496
|
config,
|
|
495
497
|
isLoading: configState === "loading",
|
|
496
|
-
isError: configState === "error"
|
|
498
|
+
isError: configState === "error",
|
|
499
|
+
retry: retryPublicConfig
|
|
497
500
|
};
|
|
498
501
|
}
|
|
499
502
|
function useSession() {
|