nexus-auth-sdk 4.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/index.d.ts +42 -0
- package/index.js +52 -0
- package/package.json +11 -0
- package/react.js +106 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
declare module '@authcore/sdk' {
|
|
2
|
+
interface AuthCoreConfig {
|
|
3
|
+
apiKey: string;
|
|
4
|
+
baseUrl?: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface RegisterParams {
|
|
8
|
+
email: string;
|
|
9
|
+
password: string;
|
|
10
|
+
username?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface LoginParams {
|
|
14
|
+
email: string;
|
|
15
|
+
password: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface AuthResponse {
|
|
19
|
+
token: string;
|
|
20
|
+
user: {
|
|
21
|
+
id: string;
|
|
22
|
+
email: string;
|
|
23
|
+
username: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface VerifyResponse {
|
|
28
|
+
valid: boolean;
|
|
29
|
+
user?: {
|
|
30
|
+
id: string;
|
|
31
|
+
email: string;
|
|
32
|
+
username: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export class AuthCore {
|
|
37
|
+
constructor(config: AuthCoreConfig);
|
|
38
|
+
register(params: RegisterParams): Promise<AuthResponse>;
|
|
39
|
+
login(params: LoginParams): Promise<AuthResponse>;
|
|
40
|
+
verify(token: string): Promise<VerifyResponse>;
|
|
41
|
+
}
|
|
42
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* nexus-auth-sdk — Auth as a Service
|
|
3
|
+
* npm install nexus-auth-sdk
|
|
4
|
+
*
|
|
5
|
+
* const { AuthCore } = require('nexus-auth-sdk');
|
|
6
|
+
* const auth = new AuthCore({ apiKey: 'nx_xxx' });
|
|
7
|
+
* const { token, user } = await auth.register({ email, password, username });
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const API = 'https://auth.miaogou.site/api';
|
|
11
|
+
|
|
12
|
+
class AuthCore {
|
|
13
|
+
constructor(config = {}) {
|
|
14
|
+
if (!config.apiKey) throw new Error('[AuthCore] apiKey is required. Get yours at https://auth.miaogou.site');
|
|
15
|
+
this.apiKey = config.apiKey;
|
|
16
|
+
this.baseUrl = config.baseUrl || API;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async _fetch(path, body) {
|
|
20
|
+
const res = await fetch(this.baseUrl + path, {
|
|
21
|
+
method: 'POST',
|
|
22
|
+
headers: { 'Content-Type': 'application/json', 'X-API-Key': this.apiKey },
|
|
23
|
+
body: JSON.stringify(body),
|
|
24
|
+
});
|
|
25
|
+
const data = await res.json();
|
|
26
|
+
if (!res.ok) throw new Error(data.message || data.error || `AuthCore API error: ${res.status}`);
|
|
27
|
+
return data;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Register a new user. Returns { token, user }. */
|
|
31
|
+
async register({ email, password, username }) {
|
|
32
|
+
if (!email || !password) throw new Error('[AuthCore] email and password are required');
|
|
33
|
+
if (password.length < 8) throw new Error('[AuthCore] password must be at least 8 characters');
|
|
34
|
+
return this._fetch('/auth/register', { email, password, username: username || email.split('@')[0] });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Login an existing user. Returns { token, user }. */
|
|
38
|
+
async login({ email, password }) {
|
|
39
|
+
if (!email || !password) throw new Error('[AuthCore] email and password are required');
|
|
40
|
+
return this._fetch('/auth/login', { email, password });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Verify a JWT token. Returns { valid, user? }. */
|
|
44
|
+
async verify(token) {
|
|
45
|
+
if (!token) throw new Error('[AuthCore] token is required');
|
|
46
|
+
return this._fetch('/auth/authenticate', { token });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ESM and CJS compatible
|
|
51
|
+
module.exports = { AuthCore };
|
|
52
|
+
if (typeof exports !== 'undefined') exports.AuthCore = AuthCore;
|
package/package.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nexus-auth-sdk",
|
|
3
|
+
"version": "4.1.0",
|
|
4
|
+
"description": "AuthCore — 认证即服务 SDK。为你的应用添加用户注册、登录、Token 验证,3 行代码接入。",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"files": ["index.js", "index.d.ts", "react.js", "react.d.ts"],
|
|
8
|
+
"keywords": ["auth", "authentication", "jwt", "authcore", "login", "register"],
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": "https://github.com/kwan/authcore-sdk"
|
|
11
|
+
}
|
package/react.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* nexus-auth-sdk/react — React bindings for AuthCore
|
|
3
|
+
*
|
|
4
|
+
* <AuthCoreProvider apiKey="nx_xxx">
|
|
5
|
+
* <SignIn />
|
|
6
|
+
* </AuthCoreProvider>
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const React = require('react');
|
|
10
|
+
const { AuthCore } = require('./index');
|
|
11
|
+
|
|
12
|
+
const AuthCoreContext = React.createContext(null);
|
|
13
|
+
|
|
14
|
+
/** Wrap your app with this provider to enable AuthCore hooks. */
|
|
15
|
+
function AuthCoreProvider({ apiKey, baseUrl, children }) {
|
|
16
|
+
const [client] = React.useState(() => new AuthCore({ apiKey, baseUrl }));
|
|
17
|
+
const [user, setUser] = React.useState(null);
|
|
18
|
+
const [token, setToken] = React.useState(null);
|
|
19
|
+
|
|
20
|
+
const value = React.useMemo(() => ({
|
|
21
|
+
client,
|
|
22
|
+
user, setUser,
|
|
23
|
+
token, setToken,
|
|
24
|
+
isSignedIn: !!token,
|
|
25
|
+
signOut: () => { setToken(null); setUser(null); },
|
|
26
|
+
}), [client, user, token]);
|
|
27
|
+
|
|
28
|
+
return React.createElement(AuthCoreContext.Provider, { value }, children);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Hook to access the AuthCore client and user state. */
|
|
32
|
+
function useAuthCore() {
|
|
33
|
+
const ctx = React.useContext(AuthCoreContext);
|
|
34
|
+
if (!ctx) throw new Error('useAuthCore must be used within <AuthCoreProvider>');
|
|
35
|
+
return ctx;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Sign-in form component with email/password. */
|
|
39
|
+
function SignIn({ onSuccess, className }) {
|
|
40
|
+
const { client, setUser, setToken } = useAuthCore();
|
|
41
|
+
const [email, setEmail] = React.useState('');
|
|
42
|
+
const [password, setPassword] = React.useState('');
|
|
43
|
+
const [error, setError] = React.useState('');
|
|
44
|
+
const [loading, setLoading] = React.useState(false);
|
|
45
|
+
|
|
46
|
+
const handleSubmit = async (e) => {
|
|
47
|
+
e.preventDefault();
|
|
48
|
+
setError('');
|
|
49
|
+
setLoading(true);
|
|
50
|
+
try {
|
|
51
|
+
const result = await client.login({ email, password });
|
|
52
|
+
setToken(result.token);
|
|
53
|
+
setUser(result.user);
|
|
54
|
+
onSuccess && onSuccess(result);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
setError(err.message);
|
|
57
|
+
}
|
|
58
|
+
setLoading(false);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return React.createElement('form', { onSubmit: handleSubmit, className, style: { display: 'flex', flexDirection: 'column', gap: 12, maxWidth: 320 } },
|
|
62
|
+
error && React.createElement('div', { style: { color: '#e05a5a', fontSize: 13, padding: '8px 12px', background: '#fee2e2', borderRadius: 8 } }, error),
|
|
63
|
+
React.createElement('input', { type: 'email', placeholder: '邮箱', value: email, onChange: e => setEmail(e.target.value), required: true, style: { padding: '10px 14px', borderRadius: 8, border: '2px solid #c4b89e', fontSize: 14 } }),
|
|
64
|
+
React.createElement('input', { type: 'password', placeholder: '密码', value: password, onChange: e => setPassword(e.target.value), required: true, style: { padding: '10px 14px', borderRadius: 8, border: '2px solid #c4b89e', fontSize: 14 } }),
|
|
65
|
+
React.createElement('button', { type: 'submit', disabled: loading, style: { padding: '10px 20px', background: '#19c8b9', color: '#fff', border: 'none', borderRadius: 50, fontWeight: 700, cursor: 'pointer', fontSize: 14 } },
|
|
66
|
+
loading ? '登录中...' : '登录'
|
|
67
|
+
)
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Sign-up form component with email/password/username. */
|
|
72
|
+
function SignUp({ onSuccess, className }) {
|
|
73
|
+
const { client, setUser, setToken } = useAuthCore();
|
|
74
|
+
const [email, setEmail] = React.useState('');
|
|
75
|
+
const [password, setPassword] = React.useState('');
|
|
76
|
+
const [username, setUsername] = React.useState('');
|
|
77
|
+
const [error, setError] = React.useState('');
|
|
78
|
+
const [loading, setLoading] = React.useState(false);
|
|
79
|
+
|
|
80
|
+
const handleSubmit = async (e) => {
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
setError('');
|
|
83
|
+
setLoading(true);
|
|
84
|
+
try {
|
|
85
|
+
const result = await client.register({ email, password, username });
|
|
86
|
+
setToken(result.token);
|
|
87
|
+
setUser(result.user);
|
|
88
|
+
onSuccess && onSuccess(result);
|
|
89
|
+
} catch (err) {
|
|
90
|
+
setError(err.message);
|
|
91
|
+
}
|
|
92
|
+
setLoading(false);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
return React.createElement('form', { onSubmit: handleSubmit, className, style: { display: 'flex', flexDirection: 'column', gap: 12, maxWidth: 320 } },
|
|
96
|
+
error && React.createElement('div', { style: { color: '#e05a5a', fontSize: 13, padding: '8px 12px', background: '#fee2e2', borderRadius: 8 } }, error),
|
|
97
|
+
React.createElement('input', { type: 'text', placeholder: '用户名', value: username, onChange: e => setUsername(e.target.value), style: { padding: '10px 14px', borderRadius: 8, border: '2px solid #c4b89e', fontSize: 14 } }),
|
|
98
|
+
React.createElement('input', { type: 'email', placeholder: '邮箱', value: email, onChange: e => setEmail(e.target.value), required: true, style: { padding: '10px 14px', borderRadius: 8, border: '2px solid #c4b89e', fontSize: 14 } }),
|
|
99
|
+
React.createElement('input', { type: 'password', placeholder: '密码(8位+,含大小写和数字)', value: password, onChange: e => setPassword(e.target.value), required: true, style: { padding: '10px 14px', borderRadius: 8, border: '2px solid #c4b89e', fontSize: 14 } }),
|
|
100
|
+
React.createElement('button', { type: 'submit', disabled: loading, style: { padding: '10px 20px', background: '#19c8b9', color: '#fff', border: 'none', borderRadius: 50, fontWeight: 700, cursor: 'pointer', fontSize: 14 } },
|
|
101
|
+
loading ? '注册中...' : '注册'
|
|
102
|
+
)
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = { AuthCoreProvider, useAuthCore, SignIn, SignUp };
|