@authon/js 0.1.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/README.md +100 -0
- package/dist/index.cjs +524 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +58 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +496 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
// src/modal.ts
|
|
2
|
+
import { DEFAULT_BRANDING } from "@authon/shared";
|
|
3
|
+
|
|
4
|
+
// src/providers.ts
|
|
5
|
+
import { PROVIDER_COLORS, PROVIDER_DISPLAY_NAMES } from "@authon/shared";
|
|
6
|
+
var PROVIDER_ICONS = {
|
|
7
|
+
google: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z"/><path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/><path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/><path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/></svg>`,
|
|
8
|
+
apple: `<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.48-3.24 0-1.44.62-2.2.44-3.06-.4C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z"/></svg>`,
|
|
9
|
+
kakao: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="#191919" d="M12 3C6.48 3 2 6.36 2 10.43c0 2.62 1.75 4.93 4.37 6.23l-1.12 4.14c-.1.36.31.65.62.44l4.93-3.26c.39.04.79.06 1.2.06 5.52 0 10-3.36 10-7.61C22 6.36 17.52 3 12 3z"/></svg>`,
|
|
10
|
+
naver: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="#fff" d="M16.27 3H7.73A4.73 4.73 0 003 7.73v8.54A4.73 4.73 0 007.73 21h8.54A4.73 4.73 0 0021 16.27V7.73A4.73 4.73 0 0016.27 3zm-1.84 12.44h-2.1l-2.86-4.15v4.15H7.38V8.56h2.1l2.86 4.15V8.56h2.09v6.88z"/></svg>`,
|
|
11
|
+
facebook: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="#fff" d="M24 12.07C24 5.41 18.63 0 12 0S0 5.4 0 12.07C0 18.1 4.39 23.1 10.13 24v-8.44H7.08v-3.49h3.04V9.41c0-3.02 1.8-4.7 4.54-4.7 1.31 0 2.68.24 2.68.24v2.97h-1.5c-1.5 0-1.96.93-1.96 1.89v2.26h3.33l-.53 3.49h-2.8V24C19.62 23.1 24 18.1 24 12.07z"/></svg>`,
|
|
12
|
+
github: `<svg viewBox="0 0 24 24" width="20" height="20" fill="#fff"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z"/></svg>`,
|
|
13
|
+
discord: `<svg viewBox="0 0 24 24" width="20" height="20" fill="#fff"><path d="M20.32 4.37a19.8 19.8 0 00-4.89-1.52.07.07 0 00-.08.04c-.21.38-.44.87-.61 1.26a18.27 18.27 0 00-5.49 0 12.64 12.64 0 00-.62-1.26.07.07 0 00-.08-.04 19.74 19.74 0 00-4.89 1.52.07.07 0 00-.03.03C1.11 8.39.34 12.28.73 16.12a.08.08 0 00.03.06 19.9 19.9 0 005.99 3.03.08.08 0 00.08-.03c.46-.63.87-1.3 1.22-2a.08.08 0 00-.04-.11 13.1 13.1 0 01-1.87-.9.08.08 0 01-.01-.13c.13-.09.25-.19.37-.29a.07.07 0 01.08-.01c3.93 1.8 8.18 1.8 12.07 0a.07.07 0 01.08 0c.12.1.25.2.37.3a.08.08 0 01-.01.12c-.6.35-1.22.65-1.87.9a.08.08 0 00-.04.1c.36.7.77 1.37 1.22 2a.08.08 0 00.08.03 19.83 19.83 0 006-3.03.08.08 0 00.03-.05c.47-4.87-.78-9.09-3.3-12.84a.06.06 0 00-.03-.03zM8.02 13.62c-1.11 0-2.03-1.02-2.03-2.28 0-1.26.9-2.28 2.03-2.28 1.14 0 2.04 1.03 2.03 2.28 0 1.26-.9 2.28-2.03 2.28zm7.5 0c-1.11 0-2.03-1.02-2.03-2.28 0-1.26.9-2.28 2.03-2.28 1.14 0 2.04 1.03 2.03 2.28 0 1.26-.89 2.28-2.03 2.28z"/></svg>`,
|
|
14
|
+
x: `<svg viewBox="0 0 24 24" width="20" height="20" fill="#fff"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>`,
|
|
15
|
+
line: `<svg viewBox="0 0 24 24" width="20" height="20" fill="#fff"><path d="M19.365 9.863c.349 0 .63.285.63.631 0 .345-.281.63-.63.63H17.61v1.125h1.755c.349 0 .63.283.63.63 0 .344-.281.629-.63.629h-2.386c-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63h2.386c.346 0 .627.285.627.63 0 .349-.281.63-.63.63H17.61v1.125h1.755zm-3.855 3.016c0 .27-.174.51-.432.596-.064.021-.133.031-.199.031-.211 0-.391-.09-.51-.25l-2.443-3.317v2.94c0 .344-.279.629-.631.629-.346 0-.626-.285-.626-.629V8.108c0-.27.173-.51.43-.595.06-.023.136-.033.194-.033.195 0 .375.104.495.254l2.462 3.33V8.108c0-.345.282-.63.63-.63.345 0 .63.285.63.63v4.771zm-5.741 0c0 .344-.282.629-.631.629-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63.346 0 .628.285.628.63v4.771zm-2.466.629H4.917c-.345 0-.63-.285-.63-.629V8.108c0-.345.285-.63.63-.63.348 0 .63.285.63.63v4.141h1.756c.348 0 .629.283.629.63 0 .344-.282.629-.629.629M24 10.314C24 4.943 18.615.572 12 .572S0 4.943 0 10.314c0 4.811 4.27 8.842 10.035 9.608.391.082.923.258 1.058.59.12.301.079.766.038 1.08l-.164 1.02c-.045.301-.24 1.186 1.049.645 1.291-.539 6.916-4.078 9.436-6.975C23.176 14.393 24 12.458 24 10.314"/></svg>`,
|
|
16
|
+
microsoft: `<svg viewBox="0 0 24 24" width="20" height="20"><rect fill="#F25022" x="1" y="1" width="10" height="10"/><rect fill="#7FBA00" x="13" y="1" width="10" height="10"/><rect fill="#00A4EF" x="1" y="13" width="10" height="10"/><rect fill="#FFB900" x="13" y="13" width="10" height="10"/></svg>`
|
|
17
|
+
};
|
|
18
|
+
function getProviderButtonConfig(provider) {
|
|
19
|
+
const colors = PROVIDER_COLORS[provider];
|
|
20
|
+
return {
|
|
21
|
+
provider,
|
|
22
|
+
label: `Continue with ${PROVIDER_DISPLAY_NAMES[provider]}`,
|
|
23
|
+
bgColor: colors.bg,
|
|
24
|
+
textColor: colors.text,
|
|
25
|
+
iconSvg: PROVIDER_ICONS[provider]
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/modal.ts
|
|
30
|
+
var ModalRenderer = class {
|
|
31
|
+
shadowRoot = null;
|
|
32
|
+
hostElement = null;
|
|
33
|
+
containerElement = null;
|
|
34
|
+
mode;
|
|
35
|
+
branding;
|
|
36
|
+
enabledProviders = [];
|
|
37
|
+
onProviderClick;
|
|
38
|
+
onEmailSubmit;
|
|
39
|
+
onClose;
|
|
40
|
+
constructor(options) {
|
|
41
|
+
this.mode = options.mode;
|
|
42
|
+
this.branding = { ...DEFAULT_BRANDING, ...options.branding };
|
|
43
|
+
this.onProviderClick = options.onProviderClick;
|
|
44
|
+
this.onEmailSubmit = options.onEmailSubmit;
|
|
45
|
+
this.onClose = options.onClose;
|
|
46
|
+
if (options.mode === "embedded" && options.containerId) {
|
|
47
|
+
this.containerElement = document.getElementById(options.containerId);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
setProviders(providers) {
|
|
51
|
+
this.enabledProviders = providers;
|
|
52
|
+
}
|
|
53
|
+
setBranding(branding) {
|
|
54
|
+
this.branding = { ...DEFAULT_BRANDING, ...branding };
|
|
55
|
+
}
|
|
56
|
+
open(view = "signIn") {
|
|
57
|
+
this.close();
|
|
58
|
+
this.render(view);
|
|
59
|
+
}
|
|
60
|
+
close() {
|
|
61
|
+
if (this.hostElement) {
|
|
62
|
+
this.hostElement.remove();
|
|
63
|
+
this.hostElement = null;
|
|
64
|
+
this.shadowRoot = null;
|
|
65
|
+
}
|
|
66
|
+
if (this.containerElement) {
|
|
67
|
+
this.containerElement.innerHTML = "";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
render(view) {
|
|
71
|
+
const host = document.createElement("div");
|
|
72
|
+
host.setAttribute("data-authon-modal", "");
|
|
73
|
+
this.hostElement = host;
|
|
74
|
+
if (this.mode === "popup") {
|
|
75
|
+
document.body.appendChild(host);
|
|
76
|
+
} else if (this.containerElement) {
|
|
77
|
+
this.containerElement.appendChild(host);
|
|
78
|
+
}
|
|
79
|
+
this.shadowRoot = host.attachShadow({ mode: "open" });
|
|
80
|
+
this.shadowRoot.innerHTML = this.buildHTML(view);
|
|
81
|
+
this.attachEvents(view);
|
|
82
|
+
}
|
|
83
|
+
buildHTML(view) {
|
|
84
|
+
const b = this.branding;
|
|
85
|
+
const isSignUp = view === "signUp";
|
|
86
|
+
const title = isSignUp ? "Create your account" : "Welcome back";
|
|
87
|
+
const subtitle = isSignUp ? "Already have an account?" : "Don't have an account?";
|
|
88
|
+
const subtitleLink = isSignUp ? "Sign in" : "Sign up";
|
|
89
|
+
const providerButtons = this.enabledProviders.filter((p) => !b.hiddenProviders?.includes(p)).map((p) => {
|
|
90
|
+
const config = getProviderButtonConfig(p);
|
|
91
|
+
return `<button class="provider-btn" data-provider="${p}" style="background:${config.bgColor};color:${config.textColor};border:1px solid ${config.bgColor === "#ffffff" ? "#e5e7eb" : config.bgColor}">
|
|
92
|
+
<span class="provider-icon">${config.iconSvg}</span>
|
|
93
|
+
<span>${config.label}</span>
|
|
94
|
+
</button>`;
|
|
95
|
+
}).join("");
|
|
96
|
+
const divider = b.showDivider !== false && b.showEmailPassword !== false ? `<div class="divider"><span>or</span></div>` : "";
|
|
97
|
+
const emailForm = b.showEmailPassword !== false ? `<form class="email-form" id="email-form">
|
|
98
|
+
<input type="email" placeholder="Email address" name="email" required class="input" />
|
|
99
|
+
<input type="password" placeholder="Password" name="password" required class="input" />
|
|
100
|
+
<button type="submit" class="submit-btn">${isSignUp ? "Sign up" : "Sign in"}</button>
|
|
101
|
+
</form>` : "";
|
|
102
|
+
const footer = b.termsUrl || b.privacyUrl ? `<div class="footer">
|
|
103
|
+
${b.termsUrl ? `<a href="${b.termsUrl}" target="_blank">Terms of Service</a>` : ""}
|
|
104
|
+
${b.termsUrl && b.privacyUrl ? " \xB7 " : ""}
|
|
105
|
+
${b.privacyUrl ? `<a href="${b.privacyUrl}" target="_blank">Privacy Policy</a>` : ""}
|
|
106
|
+
</div>` : "";
|
|
107
|
+
const popupWrapper = this.mode === "popup" ? `<div class="backdrop" id="backdrop"></div>` : "";
|
|
108
|
+
return `
|
|
109
|
+
<style>${this.buildCSS()}</style>
|
|
110
|
+
${popupWrapper}
|
|
111
|
+
<div class="modal-container" role="dialog" aria-modal="true">
|
|
112
|
+
${b.logoDataUrl ? `<img src="${b.logoDataUrl}" alt="Logo" class="logo" />` : ""}
|
|
113
|
+
<h2 class="title">${title}</h2>
|
|
114
|
+
${b.brandName ? `<p class="brand-name">${b.brandName}</p>` : ""}
|
|
115
|
+
<div class="providers">${providerButtons}</div>
|
|
116
|
+
${divider}
|
|
117
|
+
${emailForm}
|
|
118
|
+
<p class="switch-view">${subtitle} <a href="#" id="switch-link">${subtitleLink}</a></p>
|
|
119
|
+
${footer}
|
|
120
|
+
</div>
|
|
121
|
+
`;
|
|
122
|
+
}
|
|
123
|
+
buildCSS() {
|
|
124
|
+
const b = this.branding;
|
|
125
|
+
return `
|
|
126
|
+
:host {
|
|
127
|
+
--authon-primary-start: ${b.primaryColorStart || "#7c3aed"};
|
|
128
|
+
--authon-primary-end: ${b.primaryColorEnd || "#4f46e5"};
|
|
129
|
+
--authon-light-bg: ${b.lightBg || "#ffffff"};
|
|
130
|
+
--authon-light-text: ${b.lightText || "#111827"};
|
|
131
|
+
--authon-dark-bg: ${b.darkBg || "#0f172a"};
|
|
132
|
+
--authon-dark-text: ${b.darkText || "#f1f5f9"};
|
|
133
|
+
--authon-radius: ${b.borderRadius ?? 12}px;
|
|
134
|
+
--authon-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
135
|
+
font-family: var(--authon-font);
|
|
136
|
+
color: var(--authon-light-text);
|
|
137
|
+
}
|
|
138
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
139
|
+
.backdrop {
|
|
140
|
+
position: fixed; inset: 0; z-index: 99998;
|
|
141
|
+
background: rgba(0,0,0,0.5); backdrop-filter: blur(4px);
|
|
142
|
+
animation: fadeIn 0.2s ease;
|
|
143
|
+
}
|
|
144
|
+
.modal-container {
|
|
145
|
+
${this.mode === "popup" ? "position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 99999; max-height: 90vh; overflow-y: auto;" : ""}
|
|
146
|
+
background: var(--authon-light-bg);
|
|
147
|
+
border-radius: var(--authon-radius);
|
|
148
|
+
padding: 32px;
|
|
149
|
+
width: 400px; max-width: 100%;
|
|
150
|
+
${this.mode === "popup" ? "box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25); animation: slideIn 0.3s ease;" : ""}
|
|
151
|
+
}
|
|
152
|
+
.logo { display: block; margin: 0 auto 16px; max-height: 48px; }
|
|
153
|
+
.title { text-align: center; font-size: 24px; font-weight: 700; margin-bottom: 8px; }
|
|
154
|
+
.brand-name { text-align: center; font-size: 14px; color: #6b7280; margin-bottom: 24px; }
|
|
155
|
+
.providers { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
|
|
156
|
+
.provider-btn {
|
|
157
|
+
display: flex; align-items: center; gap: 12px;
|
|
158
|
+
width: 100%; padding: 10px 16px; border-radius: calc(var(--authon-radius) * 0.67);
|
|
159
|
+
font-size: 14px; font-weight: 500; cursor: pointer;
|
|
160
|
+
transition: opacity 0.15s, transform 0.1s;
|
|
161
|
+
font-family: var(--authon-font);
|
|
162
|
+
}
|
|
163
|
+
.provider-btn:hover { opacity: 0.9; }
|
|
164
|
+
.provider-btn:active { transform: scale(0.98); }
|
|
165
|
+
.provider-icon { display: flex; align-items: center; flex-shrink: 0; }
|
|
166
|
+
.divider {
|
|
167
|
+
display: flex; align-items: center; gap: 12px;
|
|
168
|
+
margin: 16px 0; color: #9ca3af; font-size: 13px;
|
|
169
|
+
}
|
|
170
|
+
.divider::before, .divider::after {
|
|
171
|
+
content: ''; flex: 1; height: 1px; background: #e5e7eb;
|
|
172
|
+
}
|
|
173
|
+
.email-form { display: flex; flex-direction: column; gap: 10px; }
|
|
174
|
+
.input {
|
|
175
|
+
width: 100%; padding: 10px 14px;
|
|
176
|
+
border: 1px solid #d1d5db; border-radius: calc(var(--authon-radius) * 0.5);
|
|
177
|
+
font-size: 14px; font-family: var(--authon-font);
|
|
178
|
+
outline: none; transition: border-color 0.15s;
|
|
179
|
+
}
|
|
180
|
+
.input:focus { border-color: var(--authon-primary-start); box-shadow: 0 0 0 3px rgba(124,58,237,0.1); }
|
|
181
|
+
.submit-btn {
|
|
182
|
+
width: 100%; padding: 10px;
|
|
183
|
+
background: linear-gradient(135deg, var(--authon-primary-start), var(--authon-primary-end));
|
|
184
|
+
color: #fff; border: none; border-radius: calc(var(--authon-radius) * 0.5);
|
|
185
|
+
font-size: 14px; font-weight: 600; cursor: pointer;
|
|
186
|
+
font-family: var(--authon-font); transition: opacity 0.15s;
|
|
187
|
+
}
|
|
188
|
+
.submit-btn:hover { opacity: 0.9; }
|
|
189
|
+
.switch-view { text-align: center; margin-top: 16px; font-size: 13px; color: #6b7280; }
|
|
190
|
+
.switch-view a { color: var(--authon-primary-start); text-decoration: none; font-weight: 500; }
|
|
191
|
+
.switch-view a:hover { text-decoration: underline; }
|
|
192
|
+
.footer { text-align: center; margin-top: 16px; font-size: 12px; color: #9ca3af; }
|
|
193
|
+
.footer a { color: #9ca3af; text-decoration: none; }
|
|
194
|
+
.footer a:hover { text-decoration: underline; }
|
|
195
|
+
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
|
196
|
+
@keyframes slideIn { from { opacity: 0; transform: translate(-50%, -48%); } to { opacity: 1; transform: translate(-50%, -50%); } }
|
|
197
|
+
${b.customCss || ""}
|
|
198
|
+
`;
|
|
199
|
+
}
|
|
200
|
+
attachEvents(view) {
|
|
201
|
+
if (!this.shadowRoot) return;
|
|
202
|
+
this.shadowRoot.querySelectorAll(".provider-btn").forEach((btn) => {
|
|
203
|
+
btn.addEventListener("click", () => {
|
|
204
|
+
const provider = btn.dataset.provider;
|
|
205
|
+
this.onProviderClick(provider);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
const form = this.shadowRoot.getElementById("email-form");
|
|
209
|
+
if (form) {
|
|
210
|
+
form.addEventListener("submit", (e) => {
|
|
211
|
+
e.preventDefault();
|
|
212
|
+
const formData = new FormData(form);
|
|
213
|
+
this.onEmailSubmit(
|
|
214
|
+
formData.get("email"),
|
|
215
|
+
formData.get("password"),
|
|
216
|
+
view === "signUp"
|
|
217
|
+
);
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
const switchLink = this.shadowRoot.getElementById("switch-link");
|
|
221
|
+
if (switchLink) {
|
|
222
|
+
switchLink.addEventListener("click", (e) => {
|
|
223
|
+
e.preventDefault();
|
|
224
|
+
this.open(view === "signIn" ? "signUp" : "signIn");
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
const backdrop = this.shadowRoot.getElementById("backdrop");
|
|
228
|
+
if (backdrop) {
|
|
229
|
+
backdrop.addEventListener("click", () => this.onClose());
|
|
230
|
+
}
|
|
231
|
+
if (this.mode === "popup") {
|
|
232
|
+
const handler = (e) => {
|
|
233
|
+
if (e.key === "Escape") {
|
|
234
|
+
this.onClose();
|
|
235
|
+
document.removeEventListener("keydown", handler);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
document.addEventListener("keydown", handler);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
// src/session.ts
|
|
244
|
+
var SessionManager = class {
|
|
245
|
+
accessToken = null;
|
|
246
|
+
user = null;
|
|
247
|
+
refreshTimer = null;
|
|
248
|
+
apiUrl;
|
|
249
|
+
publishableKey;
|
|
250
|
+
constructor(publishableKey, apiUrl) {
|
|
251
|
+
this.publishableKey = publishableKey;
|
|
252
|
+
this.apiUrl = apiUrl;
|
|
253
|
+
}
|
|
254
|
+
getToken() {
|
|
255
|
+
return this.accessToken;
|
|
256
|
+
}
|
|
257
|
+
getUser() {
|
|
258
|
+
return this.user;
|
|
259
|
+
}
|
|
260
|
+
setSession(tokens) {
|
|
261
|
+
this.accessToken = tokens.accessToken;
|
|
262
|
+
this.user = tokens.user;
|
|
263
|
+
this.scheduleRefresh(tokens.expiresIn);
|
|
264
|
+
}
|
|
265
|
+
clearSession() {
|
|
266
|
+
this.accessToken = null;
|
|
267
|
+
this.user = null;
|
|
268
|
+
if (this.refreshTimer) {
|
|
269
|
+
clearTimeout(this.refreshTimer);
|
|
270
|
+
this.refreshTimer = null;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
scheduleRefresh(expiresIn) {
|
|
274
|
+
if (this.refreshTimer) clearTimeout(this.refreshTimer);
|
|
275
|
+
const refreshIn = Math.max((expiresIn - 60) * 1e3, 5e3);
|
|
276
|
+
this.refreshTimer = setTimeout(() => this.refresh(), refreshIn);
|
|
277
|
+
}
|
|
278
|
+
async refresh() {
|
|
279
|
+
try {
|
|
280
|
+
const res = await fetch(`${this.apiUrl}/v1/auth/token/refresh`, {
|
|
281
|
+
method: "POST",
|
|
282
|
+
headers: {
|
|
283
|
+
"Content-Type": "application/json",
|
|
284
|
+
"x-api-key": this.publishableKey
|
|
285
|
+
},
|
|
286
|
+
credentials: "include"
|
|
287
|
+
});
|
|
288
|
+
if (!res.ok) {
|
|
289
|
+
this.clearSession();
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
const tokens = await res.json();
|
|
293
|
+
this.setSession(tokens);
|
|
294
|
+
return tokens;
|
|
295
|
+
} catch {
|
|
296
|
+
this.clearSession();
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
async signOut() {
|
|
301
|
+
try {
|
|
302
|
+
await fetch(`${this.apiUrl}/v1/auth/signout`, {
|
|
303
|
+
method: "POST",
|
|
304
|
+
headers: {
|
|
305
|
+
"Content-Type": "application/json",
|
|
306
|
+
"x-api-key": this.publishableKey,
|
|
307
|
+
...this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}
|
|
308
|
+
},
|
|
309
|
+
credentials: "include"
|
|
310
|
+
});
|
|
311
|
+
} catch {
|
|
312
|
+
}
|
|
313
|
+
this.clearSession();
|
|
314
|
+
}
|
|
315
|
+
destroy() {
|
|
316
|
+
this.clearSession();
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
// src/authon.ts
|
|
321
|
+
var Authon = class {
|
|
322
|
+
publishableKey;
|
|
323
|
+
config;
|
|
324
|
+
session;
|
|
325
|
+
modal = null;
|
|
326
|
+
listeners = /* @__PURE__ */ new Map();
|
|
327
|
+
branding = null;
|
|
328
|
+
providers = [];
|
|
329
|
+
initialized = false;
|
|
330
|
+
constructor(publishableKey, config) {
|
|
331
|
+
this.publishableKey = publishableKey;
|
|
332
|
+
this.config = {
|
|
333
|
+
apiUrl: config?.apiUrl || "https://api.authon.dev",
|
|
334
|
+
mode: config?.mode || "popup",
|
|
335
|
+
theme: config?.theme || "auto",
|
|
336
|
+
locale: config?.locale || "en",
|
|
337
|
+
containerId: config?.containerId,
|
|
338
|
+
appearance: config?.appearance
|
|
339
|
+
};
|
|
340
|
+
this.session = new SessionManager(publishableKey, this.config.apiUrl);
|
|
341
|
+
}
|
|
342
|
+
// ── Public API ──
|
|
343
|
+
async openSignIn() {
|
|
344
|
+
await this.ensureInitialized();
|
|
345
|
+
this.getModal().open("signIn");
|
|
346
|
+
}
|
|
347
|
+
async openSignUp() {
|
|
348
|
+
await this.ensureInitialized();
|
|
349
|
+
this.getModal().open("signUp");
|
|
350
|
+
}
|
|
351
|
+
async signInWithOAuth(provider) {
|
|
352
|
+
await this.ensureInitialized();
|
|
353
|
+
await this.startOAuthFlow(provider);
|
|
354
|
+
}
|
|
355
|
+
async signInWithEmail(email, password) {
|
|
356
|
+
const tokens = await this.apiPost("/v1/auth/signin", { email, password });
|
|
357
|
+
this.session.setSession(tokens);
|
|
358
|
+
this.emit("signedIn", tokens.user);
|
|
359
|
+
return tokens.user;
|
|
360
|
+
}
|
|
361
|
+
async signUpWithEmail(email, password, meta) {
|
|
362
|
+
const tokens = await this.apiPost("/v1/auth/signup", {
|
|
363
|
+
email,
|
|
364
|
+
password,
|
|
365
|
+
...meta
|
|
366
|
+
});
|
|
367
|
+
this.session.setSession(tokens);
|
|
368
|
+
this.emit("signedIn", tokens.user);
|
|
369
|
+
return tokens.user;
|
|
370
|
+
}
|
|
371
|
+
async signOut() {
|
|
372
|
+
await this.session.signOut();
|
|
373
|
+
this.emit("signedOut");
|
|
374
|
+
}
|
|
375
|
+
getUser() {
|
|
376
|
+
return this.session.getUser();
|
|
377
|
+
}
|
|
378
|
+
getToken() {
|
|
379
|
+
return this.session.getToken();
|
|
380
|
+
}
|
|
381
|
+
on(event, listener) {
|
|
382
|
+
if (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
383
|
+
const set = this.listeners.get(event);
|
|
384
|
+
set.add(listener);
|
|
385
|
+
return () => set.delete(listener);
|
|
386
|
+
}
|
|
387
|
+
destroy() {
|
|
388
|
+
this.modal?.close();
|
|
389
|
+
this.session.destroy();
|
|
390
|
+
this.listeners.clear();
|
|
391
|
+
}
|
|
392
|
+
// ── Internal ──
|
|
393
|
+
emit(event, ...args) {
|
|
394
|
+
this.listeners.get(event)?.forEach((fn) => fn(...args));
|
|
395
|
+
}
|
|
396
|
+
async ensureInitialized() {
|
|
397
|
+
if (this.initialized) return;
|
|
398
|
+
try {
|
|
399
|
+
const [branding, providers] = await Promise.all([
|
|
400
|
+
this.apiGet("/v1/auth/branding"),
|
|
401
|
+
this.apiGet("/v1/auth/providers")
|
|
402
|
+
]);
|
|
403
|
+
this.branding = { ...branding, ...this.config.appearance };
|
|
404
|
+
this.providers = providers.providers;
|
|
405
|
+
this.initialized = true;
|
|
406
|
+
} catch (err) {
|
|
407
|
+
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
408
|
+
throw err;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
getModal() {
|
|
412
|
+
if (!this.modal) {
|
|
413
|
+
this.modal = new ModalRenderer({
|
|
414
|
+
mode: this.config.mode,
|
|
415
|
+
containerId: this.config.containerId,
|
|
416
|
+
branding: this.branding || void 0,
|
|
417
|
+
onProviderClick: (provider) => this.startOAuthFlow(provider),
|
|
418
|
+
onEmailSubmit: (email, password, isSignUp) => {
|
|
419
|
+
if (isSignUp) {
|
|
420
|
+
this.signUpWithEmail(email, password).then(() => this.modal?.close());
|
|
421
|
+
} else {
|
|
422
|
+
this.signInWithEmail(email, password).then(() => this.modal?.close());
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
onClose: () => this.modal?.close()
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
if (this.branding) this.modal.setBranding(this.branding);
|
|
429
|
+
this.modal.setProviders(this.providers);
|
|
430
|
+
return this.modal;
|
|
431
|
+
}
|
|
432
|
+
async startOAuthFlow(provider) {
|
|
433
|
+
try {
|
|
434
|
+
const { url } = await this.apiGet(
|
|
435
|
+
`/v1/auth/oauth/${provider}/url`
|
|
436
|
+
);
|
|
437
|
+
const width = 500;
|
|
438
|
+
const height = 700;
|
|
439
|
+
const left = window.screenX + (window.outerWidth - width) / 2;
|
|
440
|
+
const top = window.screenY + (window.outerHeight - height) / 2;
|
|
441
|
+
const popup = window.open(
|
|
442
|
+
url,
|
|
443
|
+
"authon-oauth",
|
|
444
|
+
`width=${width},height=${height},left=${left},top=${top},toolbar=no,menubar=no`
|
|
445
|
+
);
|
|
446
|
+
const handler = async (e) => {
|
|
447
|
+
if (e.data?.type === "authon-oauth-callback") {
|
|
448
|
+
window.removeEventListener("message", handler);
|
|
449
|
+
popup?.close();
|
|
450
|
+
try {
|
|
451
|
+
const tokens = await this.apiPost("/v1/auth/oauth/callback", {
|
|
452
|
+
code: e.data.code,
|
|
453
|
+
state: e.data.state,
|
|
454
|
+
codeVerifier: e.data.codeVerifier,
|
|
455
|
+
provider
|
|
456
|
+
});
|
|
457
|
+
this.session.setSession(tokens);
|
|
458
|
+
this.modal?.close();
|
|
459
|
+
this.emit("signedIn", tokens.user);
|
|
460
|
+
} catch (err) {
|
|
461
|
+
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
window.addEventListener("message", handler);
|
|
466
|
+
} catch (err) {
|
|
467
|
+
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
async apiGet(path) {
|
|
471
|
+
const res = await fetch(`${this.config.apiUrl}${path}`, {
|
|
472
|
+
headers: { "x-api-key": this.publishableKey },
|
|
473
|
+
credentials: "include"
|
|
474
|
+
});
|
|
475
|
+
if (!res.ok) throw new Error(`API ${path}: ${res.status}`);
|
|
476
|
+
return res.json();
|
|
477
|
+
}
|
|
478
|
+
async apiPost(path, body) {
|
|
479
|
+
const res = await fetch(`${this.config.apiUrl}${path}`, {
|
|
480
|
+
method: "POST",
|
|
481
|
+
headers: {
|
|
482
|
+
"Content-Type": "application/json",
|
|
483
|
+
"x-api-key": this.publishableKey
|
|
484
|
+
},
|
|
485
|
+
credentials: "include",
|
|
486
|
+
body: body ? JSON.stringify(body) : void 0
|
|
487
|
+
});
|
|
488
|
+
if (!res.ok) throw new Error(`API ${path}: ${res.status}`);
|
|
489
|
+
return res.json();
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
export {
|
|
493
|
+
Authon,
|
|
494
|
+
getProviderButtonConfig
|
|
495
|
+
};
|
|
496
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/modal.ts","../src/providers.ts","../src/session.ts","../src/authon.ts"],"sourcesContent":["import type { BrandingConfig, OAuthProviderType } from '@authon/shared';\nimport { DEFAULT_BRANDING } from '@authon/shared';\nimport { getProviderButtonConfig } from './providers';\n\nexport class ModalRenderer {\n private shadowRoot: ShadowRoot | null = null;\n private hostElement: HTMLDivElement | null = null;\n private containerElement: HTMLElement | null = null;\n private mode: 'popup' | 'embedded';\n private branding: BrandingConfig;\n private enabledProviders: OAuthProviderType[] = [];\n private onProviderClick: (provider: OAuthProviderType) => void;\n private onEmailSubmit: (email: string, password: string, isSignUp: boolean) => void;\n private onClose: () => void;\n\n constructor(options: {\n mode: 'popup' | 'embedded';\n containerId?: string;\n branding?: BrandingConfig;\n onProviderClick: (provider: OAuthProviderType) => void;\n onEmailSubmit: (email: string, password: string, isSignUp: boolean) => void;\n onClose: () => void;\n }) {\n this.mode = options.mode;\n this.branding = { ...DEFAULT_BRANDING, ...options.branding };\n this.onProviderClick = options.onProviderClick;\n this.onEmailSubmit = options.onEmailSubmit;\n this.onClose = options.onClose;\n\n if (options.mode === 'embedded' && options.containerId) {\n this.containerElement = document.getElementById(options.containerId);\n }\n }\n\n setProviders(providers: OAuthProviderType[]): void {\n this.enabledProviders = providers;\n }\n\n setBranding(branding: BrandingConfig): void {\n this.branding = { ...DEFAULT_BRANDING, ...branding };\n }\n\n open(view: 'signIn' | 'signUp' = 'signIn'): void {\n this.close();\n this.render(view);\n }\n\n close(): void {\n if (this.hostElement) {\n this.hostElement.remove();\n this.hostElement = null;\n this.shadowRoot = null;\n }\n if (this.containerElement) {\n this.containerElement.innerHTML = '';\n }\n }\n\n private render(view: 'signIn' | 'signUp'): void {\n const host = document.createElement('div');\n host.setAttribute('data-authon-modal', '');\n this.hostElement = host;\n\n if (this.mode === 'popup') {\n document.body.appendChild(host);\n } else if (this.containerElement) {\n this.containerElement.appendChild(host);\n }\n\n this.shadowRoot = host.attachShadow({ mode: 'open' });\n this.shadowRoot.innerHTML = this.buildHTML(view);\n this.attachEvents(view);\n }\n\n private buildHTML(view: 'signIn' | 'signUp'): string {\n const b = this.branding;\n const isSignUp = view === 'signUp';\n const title = isSignUp ? 'Create your account' : 'Welcome back';\n const subtitle = isSignUp ? 'Already have an account?' : \"Don't have an account?\";\n const subtitleLink = isSignUp ? 'Sign in' : 'Sign up';\n\n const providerButtons = this.enabledProviders\n .filter((p) => !b.hiddenProviders?.includes(p))\n .map((p) => {\n const config = getProviderButtonConfig(p);\n return `<button class=\"provider-btn\" data-provider=\"${p}\" style=\"background:${config.bgColor};color:${config.textColor};border:1px solid ${config.bgColor === '#ffffff' ? '#e5e7eb' : config.bgColor}\">\n <span class=\"provider-icon\">${config.iconSvg}</span>\n <span>${config.label}</span>\n </button>`;\n })\n .join('');\n\n const divider =\n b.showDivider !== false && b.showEmailPassword !== false\n ? `<div class=\"divider\"><span>or</span></div>`\n : '';\n\n const emailForm =\n b.showEmailPassword !== false\n ? `<form class=\"email-form\" id=\"email-form\">\n <input type=\"email\" placeholder=\"Email address\" name=\"email\" required class=\"input\" />\n <input type=\"password\" placeholder=\"Password\" name=\"password\" required class=\"input\" />\n <button type=\"submit\" class=\"submit-btn\">${isSignUp ? 'Sign up' : 'Sign in'}</button>\n </form>`\n : '';\n\n const footer =\n b.termsUrl || b.privacyUrl\n ? `<div class=\"footer\">\n ${b.termsUrl ? `<a href=\"${b.termsUrl}\" target=\"_blank\">Terms of Service</a>` : ''}\n ${b.termsUrl && b.privacyUrl ? ' · ' : ''}\n ${b.privacyUrl ? `<a href=\"${b.privacyUrl}\" target=\"_blank\">Privacy Policy</a>` : ''}\n </div>`\n : '';\n\n const popupWrapper =\n this.mode === 'popup'\n ? `<div class=\"backdrop\" id=\"backdrop\"></div>`\n : '';\n\n return `\n <style>${this.buildCSS()}</style>\n ${popupWrapper}\n <div class=\"modal-container\" role=\"dialog\" aria-modal=\"true\">\n ${b.logoDataUrl ? `<img src=\"${b.logoDataUrl}\" alt=\"Logo\" class=\"logo\" />` : ''}\n <h2 class=\"title\">${title}</h2>\n ${b.brandName ? `<p class=\"brand-name\">${b.brandName}</p>` : ''}\n <div class=\"providers\">${providerButtons}</div>\n ${divider}\n ${emailForm}\n <p class=\"switch-view\">${subtitle} <a href=\"#\" id=\"switch-link\">${subtitleLink}</a></p>\n ${footer}\n </div>\n `;\n }\n\n private buildCSS(): string {\n const b = this.branding;\n return `\n :host {\n --authon-primary-start: ${b.primaryColorStart || '#7c3aed'};\n --authon-primary-end: ${b.primaryColorEnd || '#4f46e5'};\n --authon-light-bg: ${b.lightBg || '#ffffff'};\n --authon-light-text: ${b.lightText || '#111827'};\n --authon-dark-bg: ${b.darkBg || '#0f172a'};\n --authon-dark-text: ${b.darkText || '#f1f5f9'};\n --authon-radius: ${b.borderRadius ?? 12}px;\n --authon-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n font-family: var(--authon-font);\n color: var(--authon-light-text);\n }\n * { box-sizing: border-box; margin: 0; padding: 0; }\n .backdrop {\n position: fixed; inset: 0; z-index: 99998;\n background: rgba(0,0,0,0.5); backdrop-filter: blur(4px);\n animation: fadeIn 0.2s ease;\n }\n .modal-container {\n ${this.mode === 'popup' ? 'position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 99999; max-height: 90vh; overflow-y: auto;' : ''}\n background: var(--authon-light-bg);\n border-radius: var(--authon-radius);\n padding: 32px;\n width: 400px; max-width: 100%;\n ${this.mode === 'popup' ? 'box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25); animation: slideIn 0.3s ease;' : ''}\n }\n .logo { display: block; margin: 0 auto 16px; max-height: 48px; }\n .title { text-align: center; font-size: 24px; font-weight: 700; margin-bottom: 8px; }\n .brand-name { text-align: center; font-size: 14px; color: #6b7280; margin-bottom: 24px; }\n .providers { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }\n .provider-btn {\n display: flex; align-items: center; gap: 12px;\n width: 100%; padding: 10px 16px; border-radius: calc(var(--authon-radius) * 0.67);\n font-size: 14px; font-weight: 500; cursor: pointer;\n transition: opacity 0.15s, transform 0.1s;\n font-family: var(--authon-font);\n }\n .provider-btn:hover { opacity: 0.9; }\n .provider-btn:active { transform: scale(0.98); }\n .provider-icon { display: flex; align-items: center; flex-shrink: 0; }\n .divider {\n display: flex; align-items: center; gap: 12px;\n margin: 16px 0; color: #9ca3af; font-size: 13px;\n }\n .divider::before, .divider::after {\n content: ''; flex: 1; height: 1px; background: #e5e7eb;\n }\n .email-form { display: flex; flex-direction: column; gap: 10px; }\n .input {\n width: 100%; padding: 10px 14px;\n border: 1px solid #d1d5db; border-radius: calc(var(--authon-radius) * 0.5);\n font-size: 14px; font-family: var(--authon-font);\n outline: none; transition: border-color 0.15s;\n }\n .input:focus { border-color: var(--authon-primary-start); box-shadow: 0 0 0 3px rgba(124,58,237,0.1); }\n .submit-btn {\n width: 100%; padding: 10px;\n background: linear-gradient(135deg, var(--authon-primary-start), var(--authon-primary-end));\n color: #fff; border: none; border-radius: calc(var(--authon-radius) * 0.5);\n font-size: 14px; font-weight: 600; cursor: pointer;\n font-family: var(--authon-font); transition: opacity 0.15s;\n }\n .submit-btn:hover { opacity: 0.9; }\n .switch-view { text-align: center; margin-top: 16px; font-size: 13px; color: #6b7280; }\n .switch-view a { color: var(--authon-primary-start); text-decoration: none; font-weight: 500; }\n .switch-view a:hover { text-decoration: underline; }\n .footer { text-align: center; margin-top: 16px; font-size: 12px; color: #9ca3af; }\n .footer a { color: #9ca3af; text-decoration: none; }\n .footer a:hover { text-decoration: underline; }\n @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }\n @keyframes slideIn { from { opacity: 0; transform: translate(-50%, -48%); } to { opacity: 1; transform: translate(-50%, -50%); } }\n ${b.customCss || ''}\n `;\n }\n\n private attachEvents(view: 'signIn' | 'signUp'): void {\n if (!this.shadowRoot) return;\n\n this.shadowRoot.querySelectorAll('.provider-btn').forEach((btn) => {\n btn.addEventListener('click', () => {\n const provider = (btn as HTMLElement).dataset.provider as OAuthProviderType;\n this.onProviderClick(provider);\n });\n });\n\n const form = this.shadowRoot.getElementById('email-form') as HTMLFormElement | null;\n if (form) {\n form.addEventListener('submit', (e) => {\n e.preventDefault();\n const formData = new FormData(form);\n this.onEmailSubmit(\n formData.get('email') as string,\n formData.get('password') as string,\n view === 'signUp',\n );\n });\n }\n\n const switchLink = this.shadowRoot.getElementById('switch-link');\n if (switchLink) {\n switchLink.addEventListener('click', (e) => {\n e.preventDefault();\n this.open(view === 'signIn' ? 'signUp' : 'signIn');\n });\n }\n\n const backdrop = this.shadowRoot.getElementById('backdrop');\n if (backdrop) {\n backdrop.addEventListener('click', () => this.onClose());\n }\n\n if (this.mode === 'popup') {\n const handler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n this.onClose();\n document.removeEventListener('keydown', handler);\n }\n };\n document.addEventListener('keydown', handler);\n }\n }\n}\n","import { PROVIDER_COLORS, PROVIDER_DISPLAY_NAMES, type OAuthProviderType } from '@authon/shared';\n\nexport interface ProviderButtonConfig {\n provider: OAuthProviderType;\n label: string;\n bgColor: string;\n textColor: string;\n iconSvg: string;\n}\n\nconst PROVIDER_ICONS: Record<OAuthProviderType, string> = {\n google: `<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><path fill=\"#4285F4\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\"/><path fill=\"#34A853\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\"/><path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\"/><path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\"/></svg>`,\n apple: `<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"currentColor\"><path d=\"M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.48-3.24 0-1.44.62-2.2.44-3.06-.4C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z\"/></svg>`,\n kakao: `<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><path fill=\"#191919\" d=\"M12 3C6.48 3 2 6.36 2 10.43c0 2.62 1.75 4.93 4.37 6.23l-1.12 4.14c-.1.36.31.65.62.44l4.93-3.26c.39.04.79.06 1.2.06 5.52 0 10-3.36 10-7.61C22 6.36 17.52 3 12 3z\"/></svg>`,\n naver: `<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><path fill=\"#fff\" d=\"M16.27 3H7.73A4.73 4.73 0 003 7.73v8.54A4.73 4.73 0 007.73 21h8.54A4.73 4.73 0 0021 16.27V7.73A4.73 4.73 0 0016.27 3zm-1.84 12.44h-2.1l-2.86-4.15v4.15H7.38V8.56h2.1l2.86 4.15V8.56h2.09v6.88z\"/></svg>`,\n facebook: `<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><path fill=\"#fff\" d=\"M24 12.07C24 5.41 18.63 0 12 0S0 5.4 0 12.07C0 18.1 4.39 23.1 10.13 24v-8.44H7.08v-3.49h3.04V9.41c0-3.02 1.8-4.7 4.54-4.7 1.31 0 2.68.24 2.68.24v2.97h-1.5c-1.5 0-1.96.93-1.96 1.89v2.26h3.33l-.53 3.49h-2.8V24C19.62 23.1 24 18.1 24 12.07z\"/></svg>`,\n github: `<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"#fff\"><path d=\"M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z\"/></svg>`,\n discord: `<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"#fff\"><path d=\"M20.32 4.37a19.8 19.8 0 00-4.89-1.52.07.07 0 00-.08.04c-.21.38-.44.87-.61 1.26a18.27 18.27 0 00-5.49 0 12.64 12.64 0 00-.62-1.26.07.07 0 00-.08-.04 19.74 19.74 0 00-4.89 1.52.07.07 0 00-.03.03C1.11 8.39.34 12.28.73 16.12a.08.08 0 00.03.06 19.9 19.9 0 005.99 3.03.08.08 0 00.08-.03c.46-.63.87-1.3 1.22-2a.08.08 0 00-.04-.11 13.1 13.1 0 01-1.87-.9.08.08 0 01-.01-.13c.13-.09.25-.19.37-.29a.07.07 0 01.08-.01c3.93 1.8 8.18 1.8 12.07 0a.07.07 0 01.08 0c.12.1.25.2.37.3a.08.08 0 01-.01.12c-.6.35-1.22.65-1.87.9a.08.08 0 00-.04.1c.36.7.77 1.37 1.22 2a.08.08 0 00.08.03 19.83 19.83 0 006-3.03.08.08 0 00.03-.05c.47-4.87-.78-9.09-3.3-12.84a.06.06 0 00-.03-.03zM8.02 13.62c-1.11 0-2.03-1.02-2.03-2.28 0-1.26.9-2.28 2.03-2.28 1.14 0 2.04 1.03 2.03 2.28 0 1.26-.9 2.28-2.03 2.28zm7.5 0c-1.11 0-2.03-1.02-2.03-2.28 0-1.26.9-2.28 2.03-2.28 1.14 0 2.04 1.03 2.03 2.28 0 1.26-.89 2.28-2.03 2.28z\"/></svg>`,\n x: `<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"#fff\"><path d=\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z\"/></svg>`,\n line: `<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"#fff\"><path d=\"M19.365 9.863c.349 0 .63.285.63.631 0 .345-.281.63-.63.63H17.61v1.125h1.755c.349 0 .63.283.63.63 0 .344-.281.629-.63.629h-2.386c-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63h2.386c.346 0 .627.285.627.63 0 .349-.281.63-.63.63H17.61v1.125h1.755zm-3.855 3.016c0 .27-.174.51-.432.596-.064.021-.133.031-.199.031-.211 0-.391-.09-.51-.25l-2.443-3.317v2.94c0 .344-.279.629-.631.629-.346 0-.626-.285-.626-.629V8.108c0-.27.173-.51.43-.595.06-.023.136-.033.194-.033.195 0 .375.104.495.254l2.462 3.33V8.108c0-.345.282-.63.63-.63.345 0 .63.285.63.63v4.771zm-5.741 0c0 .344-.282.629-.631.629-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63.346 0 .628.285.628.63v4.771zm-2.466.629H4.917c-.345 0-.63-.285-.63-.629V8.108c0-.345.285-.63.63-.63.348 0 .63.285.63.63v4.141h1.756c.348 0 .629.283.629.63 0 .344-.282.629-.629.629M24 10.314C24 4.943 18.615.572 12 .572S0 4.943 0 10.314c0 4.811 4.27 8.842 10.035 9.608.391.082.923.258 1.058.59.12.301.079.766.038 1.08l-.164 1.02c-.045.301-.24 1.186 1.049.645 1.291-.539 6.916-4.078 9.436-6.975C23.176 14.393 24 12.458 24 10.314\"/></svg>`,\n microsoft: `<svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\"><rect fill=\"#F25022\" x=\"1\" y=\"1\" width=\"10\" height=\"10\"/><rect fill=\"#7FBA00\" x=\"13\" y=\"1\" width=\"10\" height=\"10\"/><rect fill=\"#00A4EF\" x=\"1\" y=\"13\" width=\"10\" height=\"10\"/><rect fill=\"#FFB900\" x=\"13\" y=\"13\" width=\"10\" height=\"10\"/></svg>`,\n};\n\nexport function getProviderButtonConfig(provider: OAuthProviderType): ProviderButtonConfig {\n const colors = PROVIDER_COLORS[provider];\n return {\n provider,\n label: `Continue with ${PROVIDER_DISPLAY_NAMES[provider]}`,\n bgColor: colors.bg,\n textColor: colors.text,\n iconSvg: PROVIDER_ICONS[provider],\n };\n}\n","import type { AuthonUser, AuthTokens } from '@authon/shared';\n\nexport class SessionManager {\n private accessToken: string | null = null;\n private user: AuthonUser | null = null;\n private refreshTimer: ReturnType<typeof setTimeout> | null = null;\n private apiUrl: string;\n private publishableKey: string;\n\n constructor(publishableKey: string, apiUrl: string) {\n this.publishableKey = publishableKey;\n this.apiUrl = apiUrl;\n }\n\n getToken(): string | null {\n return this.accessToken;\n }\n\n getUser(): AuthonUser | null {\n return this.user;\n }\n\n setSession(tokens: AuthTokens): void {\n this.accessToken = tokens.accessToken;\n this.user = tokens.user;\n this.scheduleRefresh(tokens.expiresIn);\n }\n\n clearSession(): void {\n this.accessToken = null;\n this.user = null;\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n private scheduleRefresh(expiresIn: number): void {\n if (this.refreshTimer) clearTimeout(this.refreshTimer);\n const refreshIn = Math.max((expiresIn - 60) * 1000, 5000);\n this.refreshTimer = setTimeout(() => this.refresh(), refreshIn);\n }\n\n async refresh(): Promise<AuthTokens | null> {\n try {\n const res = await fetch(`${this.apiUrl}/v1/auth/token/refresh`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.publishableKey,\n },\n credentials: 'include',\n });\n if (!res.ok) {\n this.clearSession();\n return null;\n }\n const tokens: AuthTokens = await res.json();\n this.setSession(tokens);\n return tokens;\n } catch {\n this.clearSession();\n return null;\n }\n }\n\n async signOut(): Promise<void> {\n try {\n await fetch(`${this.apiUrl}/v1/auth/signout`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.publishableKey,\n ...(this.accessToken ? { Authorization: `Bearer ${this.accessToken}` } : {}),\n },\n credentials: 'include',\n });\n } catch {\n // ignore\n }\n this.clearSession();\n }\n\n destroy(): void {\n this.clearSession();\n }\n}\n","import type { AuthonUser, AuthTokens, BrandingConfig, OAuthProviderType } from '@authon/shared';\nimport type { AuthonConfig, AuthonEventType, AuthonEvents } from './types';\nimport { ModalRenderer } from './modal';\nimport { SessionManager } from './session';\n\nexport class Authon {\n private publishableKey: string;\n private config: Required<Omit<AuthonConfig, 'containerId' | 'appearance'>> & {\n containerId?: string;\n appearance?: Partial<BrandingConfig>;\n };\n private session: SessionManager;\n private modal: ModalRenderer | null = null;\n private listeners: Map<string, Set<(...args: unknown[]) => void>> = new Map();\n private branding: BrandingConfig | null = null;\n private providers: OAuthProviderType[] = [];\n private initialized = false;\n\n constructor(publishableKey: string, config?: AuthonConfig) {\n this.publishableKey = publishableKey;\n this.config = {\n apiUrl: config?.apiUrl || 'https://api.authon.dev',\n mode: config?.mode || 'popup',\n theme: config?.theme || 'auto',\n locale: config?.locale || 'en',\n containerId: config?.containerId,\n appearance: config?.appearance,\n };\n this.session = new SessionManager(publishableKey, this.config.apiUrl);\n }\n\n // ── Public API ──\n\n async openSignIn(): Promise<void> {\n await this.ensureInitialized();\n this.getModal().open('signIn');\n }\n\n async openSignUp(): Promise<void> {\n await this.ensureInitialized();\n this.getModal().open('signUp');\n }\n\n async signInWithOAuth(provider: OAuthProviderType): Promise<void> {\n await this.ensureInitialized();\n await this.startOAuthFlow(provider);\n }\n\n async signInWithEmail(email: string, password: string): Promise<AuthonUser> {\n const tokens = await this.apiPost<AuthTokens>('/v1/auth/signin', { email, password });\n this.session.setSession(tokens);\n this.emit('signedIn', tokens.user);\n return tokens.user;\n }\n\n async signUpWithEmail(\n email: string,\n password: string,\n meta?: { displayName?: string },\n ): Promise<AuthonUser> {\n const tokens = await this.apiPost<AuthTokens>('/v1/auth/signup', {\n email,\n password,\n ...meta,\n });\n this.session.setSession(tokens);\n this.emit('signedIn', tokens.user);\n return tokens.user;\n }\n\n async signOut(): Promise<void> {\n await this.session.signOut();\n this.emit('signedOut');\n }\n\n getUser(): AuthonUser | null {\n return this.session.getUser();\n }\n\n getToken(): string | null {\n return this.session.getToken();\n }\n\n on<K extends AuthonEventType>(event: K, listener: AuthonEvents[K]): () => void {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set());\n const set = this.listeners.get(event)!;\n set.add(listener as (...args: unknown[]) => void);\n return () => set.delete(listener as (...args: unknown[]) => void);\n }\n\n destroy(): void {\n this.modal?.close();\n this.session.destroy();\n this.listeners.clear();\n }\n\n // ── Internal ──\n\n private emit(event: string, ...args: unknown[]): void {\n this.listeners.get(event)?.forEach((fn) => fn(...args));\n }\n\n private async ensureInitialized(): Promise<void> {\n if (this.initialized) return;\n try {\n const [branding, providers] = await Promise.all([\n this.apiGet<BrandingConfig>('/v1/auth/branding'),\n this.apiGet<{ providers: OAuthProviderType[] }>('/v1/auth/providers'),\n ]);\n this.branding = { ...branding, ...this.config.appearance };\n this.providers = providers.providers;\n this.initialized = true;\n } catch (err) {\n this.emit('error', err instanceof Error ? err : new Error(String(err)));\n throw err;\n }\n }\n\n private getModal(): ModalRenderer {\n if (!this.modal) {\n this.modal = new ModalRenderer({\n mode: this.config.mode,\n containerId: this.config.containerId,\n branding: this.branding || undefined,\n onProviderClick: (provider) => this.startOAuthFlow(provider),\n onEmailSubmit: (email, password, isSignUp) => {\n if (isSignUp) {\n this.signUpWithEmail(email, password).then(() => this.modal?.close());\n } else {\n this.signInWithEmail(email, password).then(() => this.modal?.close());\n }\n },\n onClose: () => this.modal?.close(),\n });\n }\n if (this.branding) this.modal.setBranding(this.branding);\n this.modal.setProviders(this.providers);\n return this.modal;\n }\n\n private async startOAuthFlow(provider: OAuthProviderType): Promise<void> {\n try {\n const { url } = await this.apiGet<{ url: string }>(\n `/v1/auth/oauth/${provider}/url`,\n );\n const width = 500;\n const height = 700;\n const left = window.screenX + (window.outerWidth - width) / 2;\n const top = window.screenY + (window.outerHeight - height) / 2;\n const popup = window.open(\n url,\n 'authon-oauth',\n `width=${width},height=${height},left=${left},top=${top},toolbar=no,menubar=no`,\n );\n\n const handler = async (e: MessageEvent) => {\n if (e.data?.type === 'authon-oauth-callback') {\n window.removeEventListener('message', handler);\n popup?.close();\n try {\n const tokens = await this.apiPost<AuthTokens>('/v1/auth/oauth/callback', {\n code: e.data.code,\n state: e.data.state,\n codeVerifier: e.data.codeVerifier,\n provider,\n });\n this.session.setSession(tokens);\n this.modal?.close();\n this.emit('signedIn', tokens.user);\n } catch (err) {\n this.emit('error', err instanceof Error ? err : new Error(String(err)));\n }\n }\n };\n window.addEventListener('message', handler);\n } catch (err) {\n this.emit('error', err instanceof Error ? err : new Error(String(err)));\n }\n }\n\n private async apiGet<T>(path: string): Promise<T> {\n const res = await fetch(`${this.config.apiUrl}${path}`, {\n headers: { 'x-api-key': this.publishableKey },\n credentials: 'include',\n });\n if (!res.ok) throw new Error(`API ${path}: ${res.status}`);\n return res.json();\n }\n\n private async apiPost<T>(path: string, body?: unknown): Promise<T> {\n const res = await fetch(`${this.config.apiUrl}${path}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.publishableKey,\n },\n credentials: 'include',\n body: body ? JSON.stringify(body) : undefined,\n });\n if (!res.ok) throw new Error(`API ${path}: ${res.status}`);\n return res.json();\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@authon/js",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Authon core browser SDK — ShadowDOM login modal, OAuth, session management",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": ["dist"],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup",
|
|
19
|
+
"dev": "tsup --watch"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/mikusnuz/authon-sdk.git",
|
|
25
|
+
"directory": "packages/js"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://github.com/mikusnuz/authon-sdk/tree/main/packages/js",
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"keywords": ["authon", "auth", "authentication", "login", "oauth", "sdk"],
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@authon/shared": "workspace:*"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"tsup": "^8.0.0",
|
|
37
|
+
"typescript": "^5.9.3"
|
|
38
|
+
}
|
|
39
|
+
}
|