central-auth-js-sdk 1.0.10
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/INTEGRATION_GUIDE.md +473 -0
- package/README.md +386 -0
- package/auth.js +159 -0
- package/core/api.js +226 -0
- package/core/env-config.js +25 -0
- package/core/events.js +28 -0
- package/core/flow.js +131 -0
- package/core/login-config.js +73 -0
- package/core/login-flow.js +148 -0
- package/core/login-state.js +50 -0
- package/core/progress-storage.js +17 -0
- package/core/state.js +55 -0
- package/index.js +20 -0
- package/login.js +318 -0
- package/package.json +35 -0
- package/signup.js +315 -0
- package/styles.css +947 -0
- package/theme.js +277 -0
- package/ui/components.js +94 -0
- package/ui/layout.js +100 -0
- package/ui/screens/email-entry.js +136 -0
- package/ui/screens/email-verify.js +96 -0
- package/ui/screens/face-registration.js +125 -0
- package/ui/screens/index.js +67 -0
- package/ui/screens/login/entry.js +63 -0
- package/ui/screens/login/frs.js +134 -0
- package/ui/screens/login/identifier-email.js +57 -0
- package/ui/screens/login/identifier-mobile.js +85 -0
- package/ui/screens/login/index.js +103 -0
- package/ui/screens/login/otp.js +79 -0
- package/ui/screens/login/password.js +65 -0
- package/ui/screens/login/success.js +32 -0
- package/ui/screens/mobile-entry.js +79 -0
- package/ui/screens/mobile-verify.js +79 -0
- package/ui/screens/password-setup.js +137 -0
- package/ui/screens/success.js +34 -0
package/core/state.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State Manager - Form data and application state
|
|
3
|
+
* UI reads/writes through this; API integration will plug in here
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export class StateManager {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.data = {
|
|
9
|
+
email: '',
|
|
10
|
+
mobile: '',
|
|
11
|
+
emailOtp: '',
|
|
12
|
+
firstName: '',
|
|
13
|
+
lastName: '',
|
|
14
|
+
mobileOtp: '',
|
|
15
|
+
password: '',
|
|
16
|
+
faceCapture: null,
|
|
17
|
+
userId: null, // from signup/email/verify response
|
|
18
|
+
loginToken: null, // from social OAuth callback
|
|
19
|
+
socialProvider: null, // 'google' | 'microsoft' when in social flow
|
|
20
|
+
error: '',
|
|
21
|
+
};
|
|
22
|
+
this.listeners = new Set();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get(key) {
|
|
26
|
+
return this.data[key];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
set(key, value) {
|
|
30
|
+
this.data[key] = value;
|
|
31
|
+
this._notify(key, value);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setMultiple(updates) {
|
|
35
|
+
Object.assign(this.data, updates);
|
|
36
|
+
this._notify('*', updates);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getAll() {
|
|
40
|
+
return { ...this.data };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
subscribe(fn) {
|
|
44
|
+
this.listeners.add(fn);
|
|
45
|
+
return () => this.listeners.delete(fn);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
_notify(key, value) {
|
|
49
|
+
this.listeners.forEach((fn) => fn(key, value, this.data));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
clearError() {
|
|
53
|
+
this.set('error', '');
|
|
54
|
+
}
|
|
55
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Central Auth Welcome Flow SDK
|
|
3
|
+
* Vanilla JavaScript - Embeddable into any web application
|
|
4
|
+
* APIs wired to Central Auth (central_auth_collection.json)
|
|
5
|
+
*
|
|
6
|
+
* Public API for host applications:
|
|
7
|
+
* initializeAuth(config) — set default configuration
|
|
8
|
+
* startSignup(config) — run sign-up flow in a container
|
|
9
|
+
* startLogin(config) — run login flow in a container
|
|
10
|
+
*
|
|
11
|
+
* Lower-level: mount (signup), mountLogin (login)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export { mount } from './signup.js';
|
|
15
|
+
export { FlowController, STEPS } from './core/flow.js';
|
|
16
|
+
export { StateManager } from './core/state.js';
|
|
17
|
+
export { createApi, dataUrlToFile } from './core/api.js';
|
|
18
|
+
export { mountLogin } from './login.js';
|
|
19
|
+
export { initializeAuth, startSignup, startLogin } from './auth.js';
|
|
20
|
+
export { applyTheme, THEME_PRESETS } from './theme.js';
|
package/login.js
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Central Auth Login Flow SDK
|
|
3
|
+
* Configurable login methods; same theme/layout as sign-up
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { createApi, dataUrlToFile } from './core/api.js';
|
|
7
|
+
import { resolveApiBaseUrl } from './core/env-config.js';
|
|
8
|
+
import { normalizeLoginConfig, getEnabledLoginMethods, LOGIN_METHODS } from './core/login-config.js';
|
|
9
|
+
import { LoginFlowController, LOGIN_STEPS } from './core/login-flow.js';
|
|
10
|
+
import { LoginStateManager } from './core/login-state.js';
|
|
11
|
+
import { createLayout } from './ui/layout.js';
|
|
12
|
+
import { createLoginScreen } from './ui/screens/login/index.js';
|
|
13
|
+
import { applyTheme } from './theme.js';
|
|
14
|
+
|
|
15
|
+
/** Parse OAuth callback (login_token, provider) from URL */
|
|
16
|
+
function parseOAuthCallback() {
|
|
17
|
+
if (typeof window === 'undefined' || !window.location) return null;
|
|
18
|
+
const params = new URLSearchParams(window.location.search);
|
|
19
|
+
const loginToken = params.get('login_token');
|
|
20
|
+
const provider = (params.get('provider') || '').toLowerCase();
|
|
21
|
+
if (!loginToken) return null;
|
|
22
|
+
if (provider !== 'google' && provider !== 'microsoft') return { loginToken, provider: 'google' };
|
|
23
|
+
return { loginToken, provider };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function clearOAuthParams() {
|
|
27
|
+
if (typeof window === 'undefined' || !window.history) return;
|
|
28
|
+
const params = new URLSearchParams(window.location.search);
|
|
29
|
+
params.delete('login_token');
|
|
30
|
+
params.delete('provider');
|
|
31
|
+
const clean = params.toString();
|
|
32
|
+
const url = window.location.pathname + (clean ? '?' + clean : '') + window.location.hash;
|
|
33
|
+
window.history.replaceState({}, '', url);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Mount the login flow
|
|
38
|
+
* @param {string|HTMLElement} container
|
|
39
|
+
* @param {Object} options - env, appIdentifier, loginMethods, frsAsSecondFactor, onLoginComplete, onContinue
|
|
40
|
+
* @param {Object} options.loginMethods - { emailPassword, mobilePassword, emailOtp, mobileOtp, social: { google, microsoft }, emailFrs }
|
|
41
|
+
* @param {boolean} options.frsAsSecondFactor - require face verification after primary auth
|
|
42
|
+
* @param {Function} [options.onLoginComplete] - Called when login completes with (payload). Payload: identifier, plus any token/fields from the final API response.
|
|
43
|
+
* @param {Function} [options.onContinue] - Called when user clicks Continue on the success screen.
|
|
44
|
+
*/
|
|
45
|
+
export function mountLogin(container, options = {}) {
|
|
46
|
+
const el = typeof container === 'string' ? document.querySelector(container) : container;
|
|
47
|
+
if (!el) {
|
|
48
|
+
console.error('[Central Auth SDK] Login container not found:', container);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const apiBaseUrl = options.apiBaseUrl ?? resolveApiBaseUrl(options);
|
|
53
|
+
const {
|
|
54
|
+
onLoginComplete = null,
|
|
55
|
+
onContinue = null,
|
|
56
|
+
onBack = null,
|
|
57
|
+
theme,
|
|
58
|
+
} = options;
|
|
59
|
+
const config = normalizeLoginConfig(options);
|
|
60
|
+
const api = createApi(apiBaseUrl);
|
|
61
|
+
const flow = new LoginFlowController(config);
|
|
62
|
+
const state = new LoginStateManager();
|
|
63
|
+
|
|
64
|
+
const layout = createLayout(el, () => {});
|
|
65
|
+
const cleanupTheme = applyTheme(layout.root, theme);
|
|
66
|
+
const showError = (msg) => layout.showError(msg);
|
|
67
|
+
|
|
68
|
+
const oauth = parseOAuthCallback();
|
|
69
|
+
if (oauth) {
|
|
70
|
+
state.set('loginToken', oauth.loginToken);
|
|
71
|
+
state.set('socialProvider', oauth.provider);
|
|
72
|
+
clearOAuthParams();
|
|
73
|
+
flow.setSocialCallback(oauth.provider);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const enabled = getEnabledLoginMethods(config);
|
|
77
|
+
if (enabled.length === 0) {
|
|
78
|
+
layout.setContent(document.createElement('div'));
|
|
79
|
+
if (layout.showError) layout.showError('No login methods enabled.');
|
|
80
|
+
return { unmount: () => layout.root.remove(), getState: () => state.getAll(), getFlow: () => flow };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!oauth && enabled.length === 1) {
|
|
84
|
+
flow.selectMethod(enabled[0].id);
|
|
85
|
+
if (flow.currentMethod === LOGIN_METHODS.SOCIAL_GOOGLE || flow.currentMethod === LOGIN_METHODS.SOCIAL_MICROSOFT) {
|
|
86
|
+
const provider = flow.currentMethod === LOGIN_METHODS.SOCIAL_MICROSOFT ? 'microsoft' : 'google';
|
|
87
|
+
const origin = typeof window !== 'undefined' && window.location ? window.location.origin : '';
|
|
88
|
+
const path = (typeof window !== 'undefined' && window.location && window.location.pathname) || '/';
|
|
89
|
+
const redirectUri = origin + path;
|
|
90
|
+
const url = provider === 'google'
|
|
91
|
+
? api.getGoogleStartUrl(redirectUri, config.appIdentifier)
|
|
92
|
+
: api.getMicrosoftStartUrl(redirectUri, config.appIdentifier);
|
|
93
|
+
window.location.href = url;
|
|
94
|
+
return { unmount: () => layout.root.remove(), getState: () => state.getAll(), getFlow: () => flow };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function buildLoginCompletePayload(apiResult) {
|
|
99
|
+
const all = state.getAll();
|
|
100
|
+
const payload = { identifier: all.identifier };
|
|
101
|
+
if (apiResult && typeof apiResult === 'object' && apiResult !== null) {
|
|
102
|
+
Object.assign(payload, apiResult);
|
|
103
|
+
}
|
|
104
|
+
return payload;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function handleIdentifierEmail(email) {
|
|
108
|
+
state.clearError();
|
|
109
|
+
state.set('identifier', email);
|
|
110
|
+
if (flow.currentMethod === LOGIN_METHODS.EMAIL_OTP) {
|
|
111
|
+
try {
|
|
112
|
+
await api.otpSend(email, '', 'email');
|
|
113
|
+
flow.goNext();
|
|
114
|
+
} catch (err) {
|
|
115
|
+
const msg = err?.data?.error || err?.message || 'Failed to send code';
|
|
116
|
+
state.set('error', msg);
|
|
117
|
+
showError(msg);
|
|
118
|
+
}
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
flow.goNext();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function handleIdentifierMobile(mobile) {
|
|
125
|
+
state.clearError();
|
|
126
|
+
state.set('identifier', mobile);
|
|
127
|
+
if (flow.currentMethod === LOGIN_METHODS.MOBILE_OTP) {
|
|
128
|
+
try {
|
|
129
|
+
await api.otpSend(mobile, '', 'sms');
|
|
130
|
+
flow.goNext();
|
|
131
|
+
} catch (err) {
|
|
132
|
+
const msg = err?.data?.error || err?.message || 'Failed to send code';
|
|
133
|
+
state.set('error', msg);
|
|
134
|
+
showError(msg);
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
flow.goNext();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function isFrRequiredError(err) {
|
|
142
|
+
const msg = (err?.data?.error || err?.message || '').toLowerCase();
|
|
143
|
+
return msg.includes('facial recognition') && msg.includes('required');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function handlePassword(password) {
|
|
147
|
+
state.clearError();
|
|
148
|
+
state.set('password', password);
|
|
149
|
+
const identifier = state.get('identifier');
|
|
150
|
+
if (config.frsAsSecondFactor) {
|
|
151
|
+
flow.goNext();
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const res = await api.loginCustom(identifier, password, config.appIdentifier, null);
|
|
156
|
+
state.set('loginResult', res);
|
|
157
|
+
flow.goNext();
|
|
158
|
+
if (typeof onLoginComplete === 'function') {
|
|
159
|
+
onLoginComplete(buildLoginCompletePayload(res));
|
|
160
|
+
}
|
|
161
|
+
} catch (err) {
|
|
162
|
+
if (isFrRequiredError(err)) {
|
|
163
|
+
flow.injectFrsStep();
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const msg = err?.data?.error || err?.message || 'Sign in failed';
|
|
167
|
+
state.set('error', msg);
|
|
168
|
+
showError(msg);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async function handleOtp(otp) {
|
|
173
|
+
state.clearError();
|
|
174
|
+
state.set('otp', otp);
|
|
175
|
+
const identifier = state.get('identifier');
|
|
176
|
+
const channel = identifier.includes('@') ? 'email' : 'sms';
|
|
177
|
+
if (config.frsAsSecondFactor) {
|
|
178
|
+
flow.goNext();
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
const res = await api.otpVerify(identifier, '', channel, otp);
|
|
183
|
+
state.set('loginResult', res);
|
|
184
|
+
flow.setStep(LOGIN_STEPS.SUCCESS);
|
|
185
|
+
if (typeof onLoginComplete === 'function') {
|
|
186
|
+
onLoginComplete(buildLoginCompletePayload(res));
|
|
187
|
+
}
|
|
188
|
+
} catch (err) {
|
|
189
|
+
if (isFrRequiredError(err)) {
|
|
190
|
+
flow.injectFrsStep();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const msg = err?.data?.error || err?.message || 'Verification failed';
|
|
194
|
+
state.set('error', msg);
|
|
195
|
+
showError(msg);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function handleFrs(dataUrl) {
|
|
200
|
+
state.clearError();
|
|
201
|
+
state.set('faceCapture', dataUrl);
|
|
202
|
+
const file = dataUrlToFile(dataUrl);
|
|
203
|
+
if (!file) {
|
|
204
|
+
showError('Please capture your face first.');
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const method = flow.currentMethod;
|
|
208
|
+
const identifier = state.get('identifier');
|
|
209
|
+
let apiResult = null;
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
if (method === LOGIN_METHODS.EMAIL_FRS) {
|
|
213
|
+
apiResult = await api.loginEmailFr(identifier, file, null, config.appIdentifier);
|
|
214
|
+
} else if (method === LOGIN_METHODS.EMAIL_PASSWORD || method === LOGIN_METHODS.MOBILE_PASSWORD) {
|
|
215
|
+
apiResult = await api.loginCustom(identifier, state.get('password'), config.appIdentifier, [file, file]);
|
|
216
|
+
} else if (method === LOGIN_METHODS.SOCIAL_GOOGLE) {
|
|
217
|
+
apiResult = await api.googleFrEnroll(state.get('loginToken'), file, null, config.appIdentifier);
|
|
218
|
+
} else if (method === LOGIN_METHODS.SOCIAL_MICROSOFT) {
|
|
219
|
+
apiResult = await api.microsoftFrEnroll(state.get('loginToken'), file, null, config.appIdentifier);
|
|
220
|
+
} else if (method === LOGIN_METHODS.EMAIL_OTP || method === LOGIN_METHODS.MOBILE_OTP) {
|
|
221
|
+
const channel = identifier.includes('@') ? 'email' : 'sms';
|
|
222
|
+
apiResult = await api.otpVerify(identifier, '', channel, state.get('otp'), [file, file]);
|
|
223
|
+
}
|
|
224
|
+
state.set('loginResult', apiResult);
|
|
225
|
+
flow.goNext();
|
|
226
|
+
if (typeof onLoginComplete === 'function') {
|
|
227
|
+
onLoginComplete(buildLoginCompletePayload(apiResult));
|
|
228
|
+
}
|
|
229
|
+
} catch (err) {
|
|
230
|
+
const msg = err?.data?.error || err?.message || 'Verification failed';
|
|
231
|
+
state.set('error', msg);
|
|
232
|
+
showError(msg);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function handleSocialRedirect(provider) {
|
|
237
|
+
state.clearError();
|
|
238
|
+
const origin = typeof window !== 'undefined' && window.location ? window.location.origin : '';
|
|
239
|
+
const path = (typeof window !== 'undefined' && window.location && window.location.pathname) || '/';
|
|
240
|
+
const redirectUri = origin + path;
|
|
241
|
+
const url = provider === 'google'
|
|
242
|
+
? api.getGoogleStartUrl(redirectUri, config.appIdentifier)
|
|
243
|
+
: api.getMicrosoftStartUrl(redirectUri, config.appIdentifier);
|
|
244
|
+
window.location.href = url;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const onSignUp = typeof options.onSignUp === 'function' ? options.onSignUp : () => {};
|
|
248
|
+
const onSuccessContinue = typeof onContinue === 'function' ? onContinue : () => {};
|
|
249
|
+
const onBackToApp = typeof onBack === 'function' ? onBack : () => { cleanupTheme(); layout.root.remove(); };
|
|
250
|
+
|
|
251
|
+
async function handleSwitchToOtp() {
|
|
252
|
+
state.clearError();
|
|
253
|
+
layout.showError('');
|
|
254
|
+
const identifier = state.get('identifier');
|
|
255
|
+
if (!identifier || !identifier.includes('@')) {
|
|
256
|
+
layout.showError('Email is required to send OTP.');
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
try {
|
|
260
|
+
await api.otpSend(identifier, '', 'email');
|
|
261
|
+
flow.switchToEmailOtp();
|
|
262
|
+
} catch (err) {
|
|
263
|
+
const msg = err?.data?.error || err?.message || 'Failed to send code';
|
|
264
|
+
state.set('error', msg);
|
|
265
|
+
layout.showError(msg);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const handlers = {
|
|
270
|
+
onSelectMethod: (methodId) => { flow.selectMethod(methodId); },
|
|
271
|
+
onIdentifierEmail: handleIdentifierEmail,
|
|
272
|
+
onIdentifierMobile: handleIdentifierMobile,
|
|
273
|
+
onPassword: handlePassword,
|
|
274
|
+
onOtp: handleOtp,
|
|
275
|
+
onFrs: handleFrs,
|
|
276
|
+
onSuccessContinue,
|
|
277
|
+
onBack: () => { state.clearError(); layout.showError(''); flow.goBack(); },
|
|
278
|
+
onBackToApp,
|
|
279
|
+
onSocialRedirect: handleSocialRedirect,
|
|
280
|
+
onSignUp,
|
|
281
|
+
onSwitchToOtp: handleSwitchToOtp,
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
function render() {
|
|
285
|
+
state.clearError();
|
|
286
|
+
layout.showError('');
|
|
287
|
+
const stepId = flow.getCurrentStep();
|
|
288
|
+
const { current, total } = flow.getProgress();
|
|
289
|
+
const progressTotal = total || 1;
|
|
290
|
+
const progressCurrent = total ? current : 1;
|
|
291
|
+
layout.updateProgress(progressCurrent, progressTotal);
|
|
292
|
+
const screen = createLoginScreen(stepId, flow, state, config, {
|
|
293
|
+
onIdentifierEmail: handlers.onIdentifierEmail,
|
|
294
|
+
onIdentifierMobile: handlers.onIdentifierMobile,
|
|
295
|
+
onPassword: handlePassword,
|
|
296
|
+
onOtp: handleOtp,
|
|
297
|
+
onFrs: handleFrs,
|
|
298
|
+
onSuccessContinue: handlers.onSuccessContinue,
|
|
299
|
+
onBack: handlers.onBack,
|
|
300
|
+
onBackToApp: handlers.onBackToApp,
|
|
301
|
+
onSelectMethod: handlers.onSelectMethod,
|
|
302
|
+
onSocialRedirect: handlers.onSocialRedirect,
|
|
303
|
+
onSignUp: handlers.onSignUp,
|
|
304
|
+
onSwitchToOtp: handlers.onSwitchToOtp,
|
|
305
|
+
});
|
|
306
|
+
layout.setContent(screen);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
flow.subscribe(render);
|
|
310
|
+
render();
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
unmount() { cleanupTheme(); layout.root.remove(); },
|
|
314
|
+
getState() { return state.getAll(); },
|
|
315
|
+
getFlow() { return flow; },
|
|
316
|
+
getCurrentStep() { return flow.getCurrentStep(); },
|
|
317
|
+
};
|
|
318
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "central-auth-js-sdk",
|
|
3
|
+
"version": "1.0.10",
|
|
4
|
+
"description": "Vanilla JS sign-up and login flow SDK — embeddable auth UI with configurable methods",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.js",
|
|
9
|
+
"./styles.css": "./styles.css"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"index.js",
|
|
13
|
+
"auth.js",
|
|
14
|
+
"theme.js",
|
|
15
|
+
"login.js",
|
|
16
|
+
"signup.js",
|
|
17
|
+
"styles.css",
|
|
18
|
+
"core",
|
|
19
|
+
"ui",
|
|
20
|
+
"README.md",
|
|
21
|
+
"INTEGRATION_GUIDE.md"
|
|
22
|
+
],
|
|
23
|
+
"keywords": [
|
|
24
|
+
"auth",
|
|
25
|
+
"signup",
|
|
26
|
+
"login",
|
|
27
|
+
"sdk",
|
|
28
|
+
"vanilla",
|
|
29
|
+
"embed"
|
|
30
|
+
],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
}
|
|
35
|
+
}
|