release: WRNexusJS 0.5.0

This commit is contained in:
2026-07-29 12:51:10 +05:30
parent 76c768099d
commit 6afe32f63f
456 changed files with 40879 additions and 8850 deletions
+55
View File
@@ -0,0 +1,55 @@
import type { AuthIdentityType, AuthPublicUser, AuthUser } from "./types.ts";
export function normalizeEmail(value: string): string {
return value.trim().toLowerCase();
}
export function normalizeUsername(value: string): string {
return value.trim().toLowerCase();
}
export function normalizePhone(value: string): string {
const trimmed = value.trim();
const prefix = trimmed.startsWith("+") ? "+" : "";
return prefix + trimmed.replace(/\D/g, "");
}
export function normalizeIdentity(type: AuthIdentityType, value: string): string {
if (type === "email") return normalizeEmail(value);
if (type === "phone") return normalizePhone(value);
return normalizeUsername(value);
}
export function inferIdentityType(value: string): AuthIdentityType {
const input = value.trim();
if (input.includes("@")) return "email";
if (/^\+?[0-9 ()-]{7,}$/.test(input)) return "phone";
return "username";
}
export function publicUser(user: AuthUser): AuthPublicUser {
return {
id: user.id,
username: user.username,
displayName: user.displayName,
avatarUrl: user.avatarUrl,
status: user.status,
roles: [...user.roles],
emailVerified: user.emailVerified,
phoneVerified: user.phoneVerified,
mfaEnabled: user.mfaEnabled,
};
}
/** Return a same-origin path for post-authentication navigation. */
export function safeAuthReturnTo(value: string | undefined, origin: string): string | undefined {
if (!value) return undefined;
try {
const base = new URL(origin);
const target = new URL(value, base);
if (target.origin !== base.origin) return undefined;
return `${target.pathname}${target.search}${target.hash}`;
} catch {
return undefined;
}
}