syntro-js-client 1.0.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.js +99 -0
- package/package.json +21 -0
- package/react.js +61 -0
package/index.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const BASE_URL = process.env.SYNTRO_API_URL || 'https://api.syntro.fun';
|
|
4
|
+
|
|
5
|
+
class Syntro {
|
|
6
|
+
constructor(apiKey) {
|
|
7
|
+
if (!apiKey) throw new Error('Syntro: apiKey is required');
|
|
8
|
+
this.apiKey = apiKey;
|
|
9
|
+
this._token = null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async _request(method, path, body, useJwt = false) {
|
|
13
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
14
|
+
|
|
15
|
+
if (useJwt && this._token) {
|
|
16
|
+
headers['Authorization'] = `Bearer ${this._token}`;
|
|
17
|
+
} else {
|
|
18
|
+
headers['x-api-key'] = this.apiKey;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const response = await fetch(`${BASE_URL}/api/v1${path}`, {
|
|
22
|
+
method,
|
|
23
|
+
headers,
|
|
24
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const data = await response.json();
|
|
28
|
+
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
const error = new Error(data.message || 'Syntro API error');
|
|
31
|
+
error.statusCode = response.status;
|
|
32
|
+
error.data = data;
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return data;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async login(email, password) {
|
|
40
|
+
const result = await this._request('POST', '/auth/login', { email, password });
|
|
41
|
+
this._token = result.accessToken;
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async register(email, password, extra = {}) {
|
|
46
|
+
return this._request('POST', '/auth/register', { email, password, ...extra });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async socialLogin(provider) {
|
|
50
|
+
const supported = ['google', 'github'];
|
|
51
|
+
if (!supported.includes(provider)) {
|
|
52
|
+
throw new Error(`Syntro: unsupported provider "${provider}". Supported: ${supported.join(', ')}`);
|
|
53
|
+
}
|
|
54
|
+
return { redirectUrl: `${BASE_URL}/api/v1/auth/social/${provider}?apiKey=${this.apiKey}` };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async forgotPassword(email) {
|
|
58
|
+
return this._request('POST', '/auth/forgot-password', { email });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async resetPassword(token, password) {
|
|
62
|
+
return this._request('POST', '/auth/reset-password', { token, password });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async me() {
|
|
66
|
+
return this._request('GET', '/auth/me', null, true);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async createBilling(name, description, amount, methods = ['card'], options = {}) {
|
|
70
|
+
return this._request('POST', '/billing/create', {
|
|
71
|
+
name,
|
|
72
|
+
description,
|
|
73
|
+
amount,
|
|
74
|
+
currency: options.currency || 'usd',
|
|
75
|
+
methods,
|
|
76
|
+
successUrl: options.successUrl,
|
|
77
|
+
cancelUrl: options.cancelUrl,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async trackEvent(type, payload = {}) {
|
|
82
|
+
return this._request('POST', '/events', { type, payload });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async getEvents(params = {}) {
|
|
86
|
+
const qs = new URLSearchParams(params).toString();
|
|
87
|
+
return this._request('GET', `/events${qs ? '?' + qs : ''}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async getStats() {
|
|
91
|
+
return this._request('GET', '/stats');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async updateStat(metric, value) {
|
|
95
|
+
return this._request('PUT', '/stats', { metric, value });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = { Syntro };
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "syntro-js-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official Node.js SDK for Syntro — plug-and-play auth, billing, and analytics for your SaaS.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"syntro",
|
|
8
|
+
"auth",
|
|
9
|
+
"billing",
|
|
10
|
+
"analytics",
|
|
11
|
+
"saas"
|
|
12
|
+
],
|
|
13
|
+
"author": "Syntro",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"node-fetch": "^3.3.2"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"react": ">=16.8.0"
|
|
20
|
+
}
|
|
21
|
+
}
|
package/react.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const React = require('react');
|
|
4
|
+
|
|
5
|
+
const SyntroContext = React.createContext(null);
|
|
6
|
+
|
|
7
|
+
const SyntroProvider = ({ client, children }) => {
|
|
8
|
+
const [user, setUser] = React.useState(null);
|
|
9
|
+
const [loading, setLoading] = React.useState(true);
|
|
10
|
+
|
|
11
|
+
React.useEffect(() => {
|
|
12
|
+
if (!client) {
|
|
13
|
+
setLoading(false);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Check if token exists or check local storage
|
|
18
|
+
client.me()
|
|
19
|
+
.then(data => setUser(data))
|
|
20
|
+
.catch(() => setUser(null))
|
|
21
|
+
.finally(() => setLoading(false));
|
|
22
|
+
}, [client]);
|
|
23
|
+
|
|
24
|
+
const value = React.useMemo(() => ({ user, loading, client }), [user, loading, client]);
|
|
25
|
+
|
|
26
|
+
return React.createElement(SyntroContext.Provider, { value }, children);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const useSyntro = () => {
|
|
30
|
+
const context = React.useContext(SyntroContext);
|
|
31
|
+
if (!context) {
|
|
32
|
+
throw new Error('useSyntro must be used within a SyntroProvider');
|
|
33
|
+
}
|
|
34
|
+
return context;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const SyntroProtected = ({ fallback = null, redirectTo = null, children }) => {
|
|
38
|
+
const { user, loading } = useSyntro();
|
|
39
|
+
|
|
40
|
+
React.useEffect(() => {
|
|
41
|
+
if (!loading && !user && redirectTo) {
|
|
42
|
+
if (typeof window !== 'undefined') {
|
|
43
|
+
window.location.href = redirectTo;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}, [user, loading, redirectTo]);
|
|
47
|
+
|
|
48
|
+
if (loading) return null;
|
|
49
|
+
|
|
50
|
+
if (!user) {
|
|
51
|
+
return fallback;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return children;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
module.exports = {
|
|
58
|
+
SyntroProvider,
|
|
59
|
+
useSyntro,
|
|
60
|
+
SyntroProtected
|
|
61
|
+
};
|