@wowsql/sdk 3.4.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/CHANGELOG.md +296 -0
- package/LICENSE +22 -0
- package/README.md +990 -0
- package/dist/auth.d.ts +160 -0
- package/dist/auth.js +320 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.js +12 -0
- package/dist/index.d.ts +180 -0
- package/dist/index.js +264 -0
- package/dist/schema.d.ts +58 -0
- package/dist/schema.js +116 -0
- package/dist/storage.d.ts +395 -0
- package/dist/storage.js +404 -0
- package/package.json +65 -0
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
export interface ProjectAuthClientConfig {
|
|
2
|
+
/** Project slug or full URL (e.g., `myproject` or `https://myproject.wowsql.com`) */
|
|
3
|
+
projectUrl: string;
|
|
4
|
+
/** Override for wowsql.com when using custom domains */
|
|
5
|
+
baseDomain?: string;
|
|
6
|
+
/** Use HTTPS (default true) */
|
|
7
|
+
secure?: boolean;
|
|
8
|
+
/** Request timeout in milliseconds */
|
|
9
|
+
timeout?: number;
|
|
10
|
+
/** Optional public API key for analytics/future enforcement */
|
|
11
|
+
publicApiKey?: string;
|
|
12
|
+
/** Custom token storage implementation (defaults to in-memory) */
|
|
13
|
+
storage?: AuthTokenStorage;
|
|
14
|
+
}
|
|
15
|
+
export interface AuthTokenStorage {
|
|
16
|
+
getAccessToken(): string | null;
|
|
17
|
+
setAccessToken(token: string | null): void;
|
|
18
|
+
getRefreshToken(): string | null;
|
|
19
|
+
setRefreshToken(token: string | null): void;
|
|
20
|
+
}
|
|
21
|
+
export interface AuthUser {
|
|
22
|
+
id: string;
|
|
23
|
+
email: string;
|
|
24
|
+
fullName?: string | null;
|
|
25
|
+
avatarUrl?: string | null;
|
|
26
|
+
emailVerified: boolean;
|
|
27
|
+
userMetadata: Record<string, any>;
|
|
28
|
+
appMetadata: Record<string, any>;
|
|
29
|
+
createdAt?: string | null;
|
|
30
|
+
}
|
|
31
|
+
export interface SignUpParams {
|
|
32
|
+
email: string;
|
|
33
|
+
password: string;
|
|
34
|
+
full_name?: string;
|
|
35
|
+
fullName?: string;
|
|
36
|
+
user_metadata?: Record<string, any>;
|
|
37
|
+
userMetadata?: Record<string, any>;
|
|
38
|
+
}
|
|
39
|
+
export interface SignInParams {
|
|
40
|
+
email: string;
|
|
41
|
+
password: string;
|
|
42
|
+
}
|
|
43
|
+
export interface AuthSession {
|
|
44
|
+
accessToken: string;
|
|
45
|
+
refreshToken: string;
|
|
46
|
+
tokenType: string;
|
|
47
|
+
expiresIn: number;
|
|
48
|
+
}
|
|
49
|
+
export interface AuthResponse {
|
|
50
|
+
user?: AuthUser;
|
|
51
|
+
session: AuthSession;
|
|
52
|
+
}
|
|
53
|
+
export interface OAuthAuthorizeResponse {
|
|
54
|
+
authorizationUrl: string;
|
|
55
|
+
provider: string;
|
|
56
|
+
redirectUri: string;
|
|
57
|
+
backendCallbackUrl?: string;
|
|
58
|
+
frontendRedirectUri?: string;
|
|
59
|
+
}
|
|
60
|
+
export declare class ProjectAuthClient {
|
|
61
|
+
private readonly config;
|
|
62
|
+
private readonly client;
|
|
63
|
+
private readonly storage;
|
|
64
|
+
private accessToken;
|
|
65
|
+
private refreshToken;
|
|
66
|
+
constructor(config: ProjectAuthClientConfig);
|
|
67
|
+
/**
|
|
68
|
+
* Register a new end user for the project.
|
|
69
|
+
*/
|
|
70
|
+
signUp(payload: SignUpParams): Promise<AuthResponse>;
|
|
71
|
+
/**
|
|
72
|
+
* Authenticate an existing user.
|
|
73
|
+
*/
|
|
74
|
+
signIn(payload: SignInParams): Promise<AuthResponse>;
|
|
75
|
+
/**
|
|
76
|
+
* Retrieve the current authenticated user.
|
|
77
|
+
*/
|
|
78
|
+
getUser(accessToken?: string): Promise<AuthUser>;
|
|
79
|
+
/**
|
|
80
|
+
* Fetch the OAuth authorization URL for a configured provider.
|
|
81
|
+
*/
|
|
82
|
+
/**
|
|
83
|
+
* Get OAuth authorization URL for the specified provider.
|
|
84
|
+
*
|
|
85
|
+
* @param provider OAuth provider name (e.g., 'github', 'google', 'facebook', 'microsoft')
|
|
86
|
+
* @param redirectUri The redirect URI where the OAuth provider will send the user after authorization.
|
|
87
|
+
* Must match the redirect URI configured in the OAuth provider settings.
|
|
88
|
+
* @returns Promise resolving to OAuth authorization URL and metadata
|
|
89
|
+
* @throws {WOWSQLError} If the request fails or the provider is not configured
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* const auth = new ProjectAuthClient({ projectUrl: 'myproject' });
|
|
94
|
+
* const result = await auth.getOAuthAuthorizationUrl(
|
|
95
|
+
* 'github',
|
|
96
|
+
* 'http://localhost:5000/auth/github/callback'
|
|
97
|
+
* );
|
|
98
|
+
* console.log(result.authorizationUrl);
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
getOAuthAuthorizationUrl(provider: string, redirectUri: string): Promise<OAuthAuthorizeResponse>;
|
|
102
|
+
/**
|
|
103
|
+
* Exchange OAuth callback code for access tokens.
|
|
104
|
+
*
|
|
105
|
+
* After the user authorizes with the OAuth provider, the provider redirects
|
|
106
|
+
* back with a code. Call this method to exchange that code for JWT tokens.
|
|
107
|
+
*
|
|
108
|
+
* @param provider - OAuth provider name (e.g., 'github', 'google')
|
|
109
|
+
* @param code - Authorization code from OAuth provider callback
|
|
110
|
+
* @param redirectUri - Optional redirect URI (uses configured one if not provided)
|
|
111
|
+
* @returns AuthResponse with session tokens and user info
|
|
112
|
+
*/
|
|
113
|
+
exchangeOAuthCallback(provider: string, code: string, redirectUri?: string): Promise<AuthResponse>;
|
|
114
|
+
/**
|
|
115
|
+
* Request password reset.
|
|
116
|
+
*
|
|
117
|
+
* Sends a password reset email to the user if they exist.
|
|
118
|
+
* Always returns success to prevent email enumeration.
|
|
119
|
+
*
|
|
120
|
+
* @param email - User's email address
|
|
121
|
+
* @returns Object with success status and message
|
|
122
|
+
*/
|
|
123
|
+
forgotPassword(email: string): Promise<{
|
|
124
|
+
success: boolean;
|
|
125
|
+
message: string;
|
|
126
|
+
}>;
|
|
127
|
+
/**
|
|
128
|
+
* Reset password with token.
|
|
129
|
+
*
|
|
130
|
+
* Validates the reset token and updates the user's password.
|
|
131
|
+
*
|
|
132
|
+
* @param token - Password reset token from email
|
|
133
|
+
* @param newPassword - New password (minimum 8 characters)
|
|
134
|
+
* @returns Object with success status and message
|
|
135
|
+
*/
|
|
136
|
+
resetPassword(token: string, newPassword: string): Promise<{
|
|
137
|
+
success: boolean;
|
|
138
|
+
message: string;
|
|
139
|
+
}>;
|
|
140
|
+
/**
|
|
141
|
+
* Get the current session tokens.
|
|
142
|
+
*/
|
|
143
|
+
getSession(): {
|
|
144
|
+
accessToken: string | null;
|
|
145
|
+
refreshToken: string | null;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Override stored session tokens (useful for SSR or persisted sessions).
|
|
149
|
+
*/
|
|
150
|
+
setSession(session: {
|
|
151
|
+
accessToken: string;
|
|
152
|
+
refreshToken?: string | null;
|
|
153
|
+
}): void;
|
|
154
|
+
/**
|
|
155
|
+
* Clear all stored tokens.
|
|
156
|
+
*/
|
|
157
|
+
clearSession(): void;
|
|
158
|
+
private persistSession;
|
|
159
|
+
private toWowError;
|
|
160
|
+
}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ProjectAuthClient = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const errors_1 = require("./errors");
|
|
9
|
+
class MemoryAuthTokenStorage {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.accessToken = null;
|
|
12
|
+
this.refreshToken = null;
|
|
13
|
+
}
|
|
14
|
+
getAccessToken() {
|
|
15
|
+
return this.accessToken;
|
|
16
|
+
}
|
|
17
|
+
setAccessToken(token) {
|
|
18
|
+
this.accessToken = token;
|
|
19
|
+
}
|
|
20
|
+
getRefreshToken() {
|
|
21
|
+
return this.refreshToken;
|
|
22
|
+
}
|
|
23
|
+
setRefreshToken(token) {
|
|
24
|
+
this.refreshToken = token;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
class ProjectAuthClient {
|
|
28
|
+
constructor(config) {
|
|
29
|
+
this.config = config;
|
|
30
|
+
const baseUrl = buildAuthBaseUrl(config.projectUrl, config.baseDomain, config.secure);
|
|
31
|
+
this.storage = config.storage || new MemoryAuthTokenStorage();
|
|
32
|
+
this.accessToken = this.storage.getAccessToken();
|
|
33
|
+
this.refreshToken = this.storage.getRefreshToken();
|
|
34
|
+
this.client = axios_1.default.create({
|
|
35
|
+
baseURL: baseUrl,
|
|
36
|
+
timeout: config.timeout ?? 30000,
|
|
37
|
+
headers: {
|
|
38
|
+
'Content-Type': 'application/json',
|
|
39
|
+
...(config.publicApiKey ? { 'X-Wow-Public-Key': config.publicApiKey } : {}),
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Register a new end user for the project.
|
|
45
|
+
*/
|
|
46
|
+
async signUp(payload) {
|
|
47
|
+
try {
|
|
48
|
+
const response = await this.client.post('/signup', normalizeSignUpPayload(payload));
|
|
49
|
+
const session = this.persistSession(response.data);
|
|
50
|
+
const user = response.data.user ? mapUser(response.data.user) : undefined;
|
|
51
|
+
return { user, session };
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw this.toWowError(error);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Authenticate an existing user.
|
|
59
|
+
*/
|
|
60
|
+
async signIn(payload) {
|
|
61
|
+
try {
|
|
62
|
+
const response = await this.client.post('/login', payload);
|
|
63
|
+
const session = this.persistSession(response.data);
|
|
64
|
+
return { session };
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw this.toWowError(error);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Retrieve the current authenticated user.
|
|
72
|
+
*/
|
|
73
|
+
async getUser(accessToken) {
|
|
74
|
+
const token = accessToken || this.accessToken || this.storage.getAccessToken();
|
|
75
|
+
if (!token) {
|
|
76
|
+
throw new errors_1.WOWSQLError('Access token is required. Please sign in first.');
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const response = await this.client.get('/me', {
|
|
80
|
+
headers: {
|
|
81
|
+
Authorization: `Bearer ${token}`,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
return mapUser(response.data);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
throw this.toWowError(error);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Fetch the OAuth authorization URL for a configured provider.
|
|
92
|
+
*/
|
|
93
|
+
/**
|
|
94
|
+
* Get OAuth authorization URL for the specified provider.
|
|
95
|
+
*
|
|
96
|
+
* @param provider OAuth provider name (e.g., 'github', 'google', 'facebook', 'microsoft')
|
|
97
|
+
* @param redirectUri The redirect URI where the OAuth provider will send the user after authorization.
|
|
98
|
+
* Must match the redirect URI configured in the OAuth provider settings.
|
|
99
|
+
* @returns Promise resolving to OAuth authorization URL and metadata
|
|
100
|
+
* @throws {WOWSQLError} If the request fails or the provider is not configured
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const auth = new ProjectAuthClient({ projectUrl: 'myproject' });
|
|
105
|
+
* const result = await auth.getOAuthAuthorizationUrl(
|
|
106
|
+
* 'github',
|
|
107
|
+
* 'http://localhost:5000/auth/github/callback'
|
|
108
|
+
* );
|
|
109
|
+
* console.log(result.authorizationUrl);
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
async getOAuthAuthorizationUrl(provider, redirectUri) {
|
|
113
|
+
if (!redirectUri || !redirectUri.trim()) {
|
|
114
|
+
throw new errors_1.WOWSQLError('redirectUri is required and cannot be empty');
|
|
115
|
+
}
|
|
116
|
+
if (!provider || !provider.trim()) {
|
|
117
|
+
throw new errors_1.WOWSQLError('provider is required and cannot be empty');
|
|
118
|
+
}
|
|
119
|
+
// Ensure redirectUri is properly formatted
|
|
120
|
+
redirectUri = redirectUri.trim();
|
|
121
|
+
try {
|
|
122
|
+
const response = await this.client.get(`/oauth/${provider}`, {
|
|
123
|
+
params: { frontend_redirect_uri: redirectUri },
|
|
124
|
+
});
|
|
125
|
+
return {
|
|
126
|
+
authorizationUrl: response.data.authorization_url,
|
|
127
|
+
provider: response.data.provider,
|
|
128
|
+
redirectUri: response.data.redirect_uri || response.data.backend_callback_url || '',
|
|
129
|
+
backendCallbackUrl: response.data.backend_callback_url,
|
|
130
|
+
frontendRedirectUri: response.data.frontend_redirect_uri,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
const axiosError = error;
|
|
135
|
+
if (axiosError.response?.status === 502) {
|
|
136
|
+
throw new errors_1.WOWSQLError(`Bad Gateway (502): The backend server may be down or unreachable. ` +
|
|
137
|
+
`Check if the backend is running and accessible at ${this.client.defaults.baseURL}`, 502, axiosError.response?.data);
|
|
138
|
+
}
|
|
139
|
+
else if (axiosError.response?.status === 400) {
|
|
140
|
+
throw new errors_1.WOWSQLError(`Bad Request (400): ${axiosError.message}. ` +
|
|
141
|
+
`Ensure OAuth provider '${provider}' is configured and enabled for this project.`, 400, axiosError.response?.data);
|
|
142
|
+
}
|
|
143
|
+
throw this.toWowError(error);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Exchange OAuth callback code for access tokens.
|
|
148
|
+
*
|
|
149
|
+
* After the user authorizes with the OAuth provider, the provider redirects
|
|
150
|
+
* back with a code. Call this method to exchange that code for JWT tokens.
|
|
151
|
+
*
|
|
152
|
+
* @param provider - OAuth provider name (e.g., 'github', 'google')
|
|
153
|
+
* @param code - Authorization code from OAuth provider callback
|
|
154
|
+
* @param redirectUri - Optional redirect URI (uses configured one if not provided)
|
|
155
|
+
* @returns AuthResponse with session tokens and user info
|
|
156
|
+
*/
|
|
157
|
+
async exchangeOAuthCallback(provider, code, redirectUri) {
|
|
158
|
+
try {
|
|
159
|
+
const response = await this.client.post(`/oauth/${provider}/callback`, {
|
|
160
|
+
code,
|
|
161
|
+
redirect_uri: redirectUri,
|
|
162
|
+
});
|
|
163
|
+
const session = this.persistSession(response.data);
|
|
164
|
+
const user = response.data.user ? mapUser(response.data.user) : undefined;
|
|
165
|
+
return { user, session };
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
throw this.toWowError(error);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Request password reset.
|
|
173
|
+
*
|
|
174
|
+
* Sends a password reset email to the user if they exist.
|
|
175
|
+
* Always returns success to prevent email enumeration.
|
|
176
|
+
*
|
|
177
|
+
* @param email - User's email address
|
|
178
|
+
* @returns Object with success status and message
|
|
179
|
+
*/
|
|
180
|
+
async forgotPassword(email) {
|
|
181
|
+
try {
|
|
182
|
+
const response = await this.client.post('/forgot-password', { email });
|
|
183
|
+
return {
|
|
184
|
+
success: response.data.success ?? true,
|
|
185
|
+
message: response.data.message ?? 'If that email exists, a password reset link has been sent'
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
throw this.toWowError(error);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Reset password with token.
|
|
194
|
+
*
|
|
195
|
+
* Validates the reset token and updates the user's password.
|
|
196
|
+
*
|
|
197
|
+
* @param token - Password reset token from email
|
|
198
|
+
* @param newPassword - New password (minimum 8 characters)
|
|
199
|
+
* @returns Object with success status and message
|
|
200
|
+
*/
|
|
201
|
+
async resetPassword(token, newPassword) {
|
|
202
|
+
try {
|
|
203
|
+
const response = await this.client.post('/reset-password', {
|
|
204
|
+
token,
|
|
205
|
+
new_password: newPassword
|
|
206
|
+
});
|
|
207
|
+
return {
|
|
208
|
+
success: response.data.success ?? true,
|
|
209
|
+
message: response.data.message ?? 'Password reset successfully! You can now login with your new password'
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
throw this.toWowError(error);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Get the current session tokens.
|
|
218
|
+
*/
|
|
219
|
+
getSession() {
|
|
220
|
+
return {
|
|
221
|
+
accessToken: this.accessToken || this.storage.getAccessToken(),
|
|
222
|
+
refreshToken: this.refreshToken || this.storage.getRefreshToken(),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Override stored session tokens (useful for SSR or persisted sessions).
|
|
227
|
+
*/
|
|
228
|
+
setSession(session) {
|
|
229
|
+
this.accessToken = session.accessToken;
|
|
230
|
+
this.refreshToken = session.refreshToken ?? null;
|
|
231
|
+
this.storage.setAccessToken(this.accessToken);
|
|
232
|
+
this.storage.setRefreshToken(this.refreshToken);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Clear all stored tokens.
|
|
236
|
+
*/
|
|
237
|
+
clearSession() {
|
|
238
|
+
this.accessToken = null;
|
|
239
|
+
this.refreshToken = null;
|
|
240
|
+
this.storage.setAccessToken(null);
|
|
241
|
+
this.storage.setRefreshToken(null);
|
|
242
|
+
}
|
|
243
|
+
persistSession(raw) {
|
|
244
|
+
const session = mapSession(raw);
|
|
245
|
+
this.accessToken = session.accessToken;
|
|
246
|
+
this.refreshToken = session.refreshToken;
|
|
247
|
+
this.storage.setAccessToken(session.accessToken);
|
|
248
|
+
this.storage.setRefreshToken(session.refreshToken);
|
|
249
|
+
return session;
|
|
250
|
+
}
|
|
251
|
+
toWowError(error) {
|
|
252
|
+
if (error instanceof errors_1.WOWSQLError) {
|
|
253
|
+
return error;
|
|
254
|
+
}
|
|
255
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
256
|
+
const axiosError = error;
|
|
257
|
+
const status = axiosError.response?.status;
|
|
258
|
+
const detail = axiosError.response?.data?.detail ||
|
|
259
|
+
axiosError.response?.data?.message ||
|
|
260
|
+
axiosError.message;
|
|
261
|
+
return new errors_1.WOWSQLError(detail || 'Request failed', status, axiosError.response?.data);
|
|
262
|
+
}
|
|
263
|
+
return new errors_1.WOWSQLError(error?.message || 'Unknown error');
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
exports.ProjectAuthClient = ProjectAuthClient;
|
|
267
|
+
function buildAuthBaseUrl(projectUrl, baseDomain = 'wowsql.com', secure = true) {
|
|
268
|
+
let normalized = projectUrl.trim();
|
|
269
|
+
// If it's already a full URL, use it as-is
|
|
270
|
+
if (normalized.startsWith('http://') || normalized.startsWith('https://')) {
|
|
271
|
+
normalized = normalized.replace(/\/+$/, '');
|
|
272
|
+
if (normalized.endsWith('/api')) {
|
|
273
|
+
normalized = normalized.slice(0, -4);
|
|
274
|
+
}
|
|
275
|
+
return `${normalized}/api/auth`;
|
|
276
|
+
}
|
|
277
|
+
// If it already contains the base domain, don't append it again
|
|
278
|
+
if (normalized.includes(`.${baseDomain}`) || normalized.endsWith(baseDomain)) {
|
|
279
|
+
const protocol = secure ? 'https' : 'http';
|
|
280
|
+
normalized = `${protocol}://${normalized}`;
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
// Just a project slug, append domain
|
|
284
|
+
const protocol = secure ? 'https' : 'http';
|
|
285
|
+
normalized = `${protocol}://${normalized}.${baseDomain}`;
|
|
286
|
+
}
|
|
287
|
+
normalized = normalized.replace(/\/+$/, '');
|
|
288
|
+
if (normalized.endsWith('/api')) {
|
|
289
|
+
normalized = normalized.slice(0, -4);
|
|
290
|
+
}
|
|
291
|
+
return `${normalized}/api/auth`;
|
|
292
|
+
}
|
|
293
|
+
function normalizeSignUpPayload(payload) {
|
|
294
|
+
return {
|
|
295
|
+
email: payload.email,
|
|
296
|
+
password: payload.password,
|
|
297
|
+
full_name: payload.full_name ?? payload.fullName,
|
|
298
|
+
user_metadata: payload.user_metadata ?? payload.userMetadata,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
function mapSession(data) {
|
|
302
|
+
return {
|
|
303
|
+
accessToken: data.access_token,
|
|
304
|
+
refreshToken: data.refresh_token,
|
|
305
|
+
tokenType: data.token_type ?? 'bearer',
|
|
306
|
+
expiresIn: data.expires_in ?? 0,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
function mapUser(data) {
|
|
310
|
+
return {
|
|
311
|
+
id: data.id,
|
|
312
|
+
email: data.email,
|
|
313
|
+
fullName: data.full_name ?? data.fullName ?? null,
|
|
314
|
+
avatarUrl: data.avatar_url ?? data.avatarUrl ?? null,
|
|
315
|
+
emailVerified: Boolean(data.email_verified ?? data.emailVerified),
|
|
316
|
+
userMetadata: data.user_metadata ?? data.userMetadata ?? {},
|
|
317
|
+
appMetadata: data.app_metadata ?? data.appMetadata ?? {},
|
|
318
|
+
createdAt: data.created_at ?? data.createdAt ?? null,
|
|
319
|
+
};
|
|
320
|
+
}
|
package/dist/errors.d.ts
ADDED
package/dist/errors.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WOWSQLError = void 0;
|
|
4
|
+
class WOWSQLError extends Error {
|
|
5
|
+
constructor(message, statusCode, response) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.statusCode = statusCode;
|
|
8
|
+
this.response = response;
|
|
9
|
+
this.name = 'WOWSQLError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.WOWSQLError = WOWSQLError;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WowSQL TypeScript SDK
|
|
3
|
+
* Official client library for WowSQL REST API v2
|
|
4
|
+
*
|
|
5
|
+
* @version 2.0.0
|
|
6
|
+
* @license MIT
|
|
7
|
+
* @see https://github.com/wowsql/wowsql
|
|
8
|
+
*/
|
|
9
|
+
import { AxiosInstance } from 'axios';
|
|
10
|
+
export interface WowSQLConfig {
|
|
11
|
+
/** Project subdomain or full URL (e.g., 'myproject' or 'https://myproject.wowsql.com') */
|
|
12
|
+
projectUrl: string;
|
|
13
|
+
/** API key for authentication */
|
|
14
|
+
apiKey: string;
|
|
15
|
+
/** Base domain (default: wowsql.com) */
|
|
16
|
+
baseDomain?: string;
|
|
17
|
+
/** Use HTTPS (default: true) */
|
|
18
|
+
secure?: boolean;
|
|
19
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
20
|
+
timeout?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface QueryOptions {
|
|
23
|
+
/** Columns to select (comma-separated or array) */
|
|
24
|
+
select?: string | string[];
|
|
25
|
+
/** Filter expressions */
|
|
26
|
+
filter?: FilterExpression | FilterExpression[];
|
|
27
|
+
/** Column to sort by */
|
|
28
|
+
order?: string;
|
|
29
|
+
/** Sort direction */
|
|
30
|
+
orderDirection?: 'asc' | 'desc';
|
|
31
|
+
/** Maximum records to return */
|
|
32
|
+
limit?: number;
|
|
33
|
+
/** Number of records to skip */
|
|
34
|
+
offset?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface FilterExpression {
|
|
37
|
+
column: string;
|
|
38
|
+
operator: 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'like' | 'is';
|
|
39
|
+
value: string | number | boolean | null;
|
|
40
|
+
}
|
|
41
|
+
export interface QueryResponse<T = any> {
|
|
42
|
+
data: T[];
|
|
43
|
+
count: number;
|
|
44
|
+
total: number;
|
|
45
|
+
limit: number;
|
|
46
|
+
offset: number;
|
|
47
|
+
}
|
|
48
|
+
export interface CreateResponse {
|
|
49
|
+
id: number | string;
|
|
50
|
+
message: string;
|
|
51
|
+
}
|
|
52
|
+
export interface UpdateResponse {
|
|
53
|
+
message: string;
|
|
54
|
+
affected_rows: number;
|
|
55
|
+
}
|
|
56
|
+
export interface DeleteResponse {
|
|
57
|
+
message: string;
|
|
58
|
+
affected_rows: number;
|
|
59
|
+
}
|
|
60
|
+
export interface TableSchema {
|
|
61
|
+
table: string;
|
|
62
|
+
columns: ColumnInfo[];
|
|
63
|
+
primary_key: string | null;
|
|
64
|
+
}
|
|
65
|
+
export interface ColumnInfo {
|
|
66
|
+
name: string;
|
|
67
|
+
type: string;
|
|
68
|
+
nullable: boolean;
|
|
69
|
+
key: string;
|
|
70
|
+
default: any;
|
|
71
|
+
extra: string;
|
|
72
|
+
}
|
|
73
|
+
export declare class WowSQLClient {
|
|
74
|
+
private client;
|
|
75
|
+
private baseUrl;
|
|
76
|
+
constructor(config: WowSQLConfig);
|
|
77
|
+
/**
|
|
78
|
+
* Get a table interface for fluent API
|
|
79
|
+
*/
|
|
80
|
+
table<T = any>(tableName: string): Table<T>;
|
|
81
|
+
/**
|
|
82
|
+
* List all tables in the database
|
|
83
|
+
*/
|
|
84
|
+
listTables(): Promise<string[]>;
|
|
85
|
+
/**
|
|
86
|
+
* Get table schema
|
|
87
|
+
*/
|
|
88
|
+
getTableSchema(tableName: string): Promise<TableSchema>;
|
|
89
|
+
/**
|
|
90
|
+
* Execute raw SQL query (read-only for safety)
|
|
91
|
+
*/
|
|
92
|
+
query<T = any>(sql: string): Promise<T[]>;
|
|
93
|
+
/**
|
|
94
|
+
* Health check
|
|
95
|
+
*/
|
|
96
|
+
health(): Promise<{
|
|
97
|
+
status: string;
|
|
98
|
+
timestamp: string;
|
|
99
|
+
}>;
|
|
100
|
+
}
|
|
101
|
+
export declare class Table<T = any> {
|
|
102
|
+
private client;
|
|
103
|
+
private tableName;
|
|
104
|
+
constructor(client: AxiosInstance, tableName: string);
|
|
105
|
+
/**
|
|
106
|
+
* Query records with filters and pagination
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* const users = await client.table('users')
|
|
110
|
+
* .select(['id', 'name', 'email'])
|
|
111
|
+
* .filter({ column: 'age', operator: 'gt', value: 18 })
|
|
112
|
+
* .order('created_at', 'desc')
|
|
113
|
+
* .limit(10)
|
|
114
|
+
* .get();
|
|
115
|
+
*/
|
|
116
|
+
select(columns: string | string[]): QueryBuilder<T>;
|
|
117
|
+
/**
|
|
118
|
+
* Query with filter
|
|
119
|
+
*/
|
|
120
|
+
filter(filter: FilterExpression): QueryBuilder<T>;
|
|
121
|
+
/**
|
|
122
|
+
* Get all records (with optional limit)
|
|
123
|
+
*/
|
|
124
|
+
get(options?: QueryOptions): Promise<QueryResponse<T>>;
|
|
125
|
+
/**
|
|
126
|
+
* Get a single record by ID
|
|
127
|
+
*/
|
|
128
|
+
getById(id: string | number): Promise<T>;
|
|
129
|
+
/**
|
|
130
|
+
* Create a new record
|
|
131
|
+
*/
|
|
132
|
+
create(data: Partial<T>): Promise<CreateResponse>;
|
|
133
|
+
/**
|
|
134
|
+
* Update a record by ID
|
|
135
|
+
*/
|
|
136
|
+
update(id: string | number, data: Partial<T>): Promise<UpdateResponse>;
|
|
137
|
+
/**
|
|
138
|
+
* Delete a record by ID
|
|
139
|
+
*/
|
|
140
|
+
delete(id: string | number): Promise<DeleteResponse>;
|
|
141
|
+
}
|
|
142
|
+
export declare class QueryBuilder<T = any> {
|
|
143
|
+
private client;
|
|
144
|
+
private tableName;
|
|
145
|
+
private options;
|
|
146
|
+
constructor(client: AxiosInstance, tableName: string);
|
|
147
|
+
/**
|
|
148
|
+
* Select specific columns
|
|
149
|
+
*/
|
|
150
|
+
select(columns: string | string[]): this;
|
|
151
|
+
/**
|
|
152
|
+
* Add filter condition
|
|
153
|
+
*/
|
|
154
|
+
filter(filter: FilterExpression): this;
|
|
155
|
+
/**
|
|
156
|
+
* Order by column
|
|
157
|
+
*/
|
|
158
|
+
order(column: string, direction?: 'asc' | 'desc'): this;
|
|
159
|
+
/**
|
|
160
|
+
* Limit number of results
|
|
161
|
+
*/
|
|
162
|
+
limit(limit: number): this;
|
|
163
|
+
/**
|
|
164
|
+
* Skip records (pagination)
|
|
165
|
+
*/
|
|
166
|
+
offset(offset: number): this;
|
|
167
|
+
/**
|
|
168
|
+
* Execute query
|
|
169
|
+
*/
|
|
170
|
+
get(additionalOptions?: QueryOptions): Promise<QueryResponse<T>>;
|
|
171
|
+
/**
|
|
172
|
+
* Get first record
|
|
173
|
+
*/
|
|
174
|
+
first(): Promise<T | null>;
|
|
175
|
+
}
|
|
176
|
+
export * from './storage';
|
|
177
|
+
export * from './auth';
|
|
178
|
+
export * from './schema';
|
|
179
|
+
export * from './errors';
|
|
180
|
+
export default WowSQLClient;
|