@gymspace/sdk 1.0.2 → 1.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/dist/index.d.mts +2065 -0
- package/dist/index.d.ts +2065 -0
- package/dist/index.js +25 -73
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +25 -73
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +3 -87
- package/src/models/auth.ts +3 -14
- package/src/models/organizations.ts +16 -0
- package/src/resources/auth.ts +1 -1
- package/src/resources/onboarding.ts +2 -2
- package/src/resources/organizations.ts +5 -1
- package/src/sdk.ts +0 -6
package/src/client.ts
CHANGED
|
@@ -3,6 +3,7 @@ import axios, {
|
|
|
3
3
|
AxiosRequestConfig,
|
|
4
4
|
AxiosError,
|
|
5
5
|
InternalAxiosRequestConfig,
|
|
6
|
+
AxiosRequestHeaders,
|
|
6
7
|
} from 'axios';
|
|
7
8
|
import { GymSpaceConfig, RequestOptions } from './types';
|
|
8
9
|
import {
|
|
@@ -17,11 +18,6 @@ import {
|
|
|
17
18
|
export class ApiClient {
|
|
18
19
|
private axiosInstance: AxiosInstance;
|
|
19
20
|
private config: GymSpaceConfig;
|
|
20
|
-
private refreshPromise: Promise<any> | null = null; // To prevent concurrent refresh attempts
|
|
21
|
-
|
|
22
|
-
// Callbacks for token updates and auth errors
|
|
23
|
-
public onTokensUpdated?: (accessToken: string, refreshToken: string) => void;
|
|
24
|
-
public onAuthError?: (error: any) => void;
|
|
25
21
|
|
|
26
22
|
constructor(config: GymSpaceConfig) {
|
|
27
23
|
this.config = config;
|
|
@@ -47,11 +43,6 @@ export class ApiClient {
|
|
|
47
43
|
config.headers['Authorization'] = `Bearer ${this.config.apiKey}`;
|
|
48
44
|
}
|
|
49
45
|
|
|
50
|
-
// Add refresh token header if available
|
|
51
|
-
if (this.config.refreshToken && config.headers) {
|
|
52
|
-
config.headers['X-Refresh-Token'] = this.config.refreshToken;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
46
|
return config;
|
|
56
47
|
},
|
|
57
48
|
(error) => {
|
|
@@ -59,86 +50,18 @@ export class ApiClient {
|
|
|
59
50
|
},
|
|
60
51
|
);
|
|
61
52
|
|
|
62
|
-
// Response interceptor
|
|
53
|
+
// Response interceptor - simplified without automatic token refresh
|
|
63
54
|
this.axiosInstance.interceptors.response.use(
|
|
64
55
|
(response) => {
|
|
65
|
-
// Check for new tokens in response headers
|
|
66
|
-
const newAccessToken = response.headers['x-new-access-token'];
|
|
67
|
-
const newRefreshToken = response.headers['x-new-refresh-token'];
|
|
68
|
-
|
|
69
|
-
if (newAccessToken && newRefreshToken) {
|
|
70
|
-
this.setTokens(newAccessToken, newRefreshToken);
|
|
71
|
-
// Emit token update event if needed
|
|
72
|
-
this.onTokensUpdated?.(newAccessToken, newRefreshToken);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
56
|
return response;
|
|
76
57
|
},
|
|
77
58
|
async (error: AxiosError) => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
// If it's a 401 error and we haven't retried yet, try to refresh the token
|
|
81
|
-
if (error.response?.status === 401 && !originalRequest._retry && this.config.refreshToken) {
|
|
82
|
-
originalRequest._retry = true;
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
// Prevent concurrent refresh attempts
|
|
86
|
-
if (!this.refreshPromise) {
|
|
87
|
-
this.refreshPromise = this.refreshAccessToken();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const newTokens = await this.refreshPromise;
|
|
91
|
-
this.refreshPromise = null;
|
|
92
|
-
|
|
93
|
-
if (newTokens) {
|
|
94
|
-
// Update the original request with new token
|
|
95
|
-
originalRequest.headers = originalRequest.headers || {};
|
|
96
|
-
originalRequest.headers['Authorization'] = `Bearer ${newTokens.access_token}`;
|
|
97
|
-
|
|
98
|
-
// Retry the original request
|
|
99
|
-
return this.axiosInstance(originalRequest);
|
|
100
|
-
}
|
|
101
|
-
} catch (refreshError) {
|
|
102
|
-
this.refreshPromise = null;
|
|
103
|
-
// If refresh fails, clear tokens and emit error
|
|
104
|
-
this.clearAuth();
|
|
105
|
-
this.onAuthError?.(refreshError);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
59
|
+
// Simply throw the error - no automatic refresh attempts
|
|
109
60
|
throw this.handleError(error);
|
|
110
61
|
},
|
|
111
62
|
);
|
|
112
63
|
}
|
|
113
64
|
|
|
114
|
-
/**
|
|
115
|
-
* Refresh the access token using the stored refresh token
|
|
116
|
-
*/
|
|
117
|
-
private async refreshAccessToken(): Promise<any> {
|
|
118
|
-
if (!this.config.refreshToken) {
|
|
119
|
-
throw new AuthenticationError('No refresh token available');
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
try {
|
|
123
|
-
const response = await axios.post(
|
|
124
|
-
`${this.config.baseURL}/auth/refresh`,
|
|
125
|
-
{ refresh_token: this.config.refreshToken },
|
|
126
|
-
{
|
|
127
|
-
headers: {
|
|
128
|
-
'Content-Type': 'application/json',
|
|
129
|
-
},
|
|
130
|
-
timeout: this.config.timeout || 30000,
|
|
131
|
-
}
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
const newTokens = response.data;
|
|
135
|
-
this.setTokens(newTokens.access_token, newTokens.refresh_token);
|
|
136
|
-
|
|
137
|
-
return newTokens;
|
|
138
|
-
} catch (error) {
|
|
139
|
-
throw new AuthenticationError('Failed to refresh token');
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
65
|
|
|
143
66
|
private handleError(error: AxiosError): GymSpaceError {
|
|
144
67
|
const requestPath = error.config?.url || 'unknown';
|
|
@@ -245,19 +168,12 @@ export class ApiClient {
|
|
|
245
168
|
this.config.apiKey = token;
|
|
246
169
|
}
|
|
247
170
|
|
|
248
|
-
setTokens(accessToken: string, refreshToken: string): void {
|
|
249
|
-
this.config.apiKey = accessToken;
|
|
250
|
-
// Store refresh token if needed for token refresh logic
|
|
251
|
-
this.config.refreshToken = refreshToken;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
171
|
setGymId(gymId: string): void {
|
|
255
172
|
this.axiosInstance.defaults.headers.common['X-Gym-Id'] = gymId;
|
|
256
173
|
}
|
|
257
174
|
|
|
258
175
|
clearAuth(): void {
|
|
259
176
|
delete this.config.apiKey;
|
|
260
|
-
delete this.config.refreshToken;
|
|
261
177
|
delete this.axiosInstance.defaults.headers.common['Authorization'];
|
|
262
178
|
delete this.axiosInstance.defaults.headers.common['X-Gym-Id'];
|
|
263
179
|
}
|
package/src/models/auth.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { SubscriptionPlan } from './subscriptions';
|
|
2
|
+
|
|
1
3
|
export interface RegisterOwnerDto {
|
|
2
4
|
name: string;
|
|
3
5
|
email: string;
|
|
@@ -79,7 +81,6 @@ export interface ResendResetCodeResponseDto {
|
|
|
79
81
|
message: string;
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
|
|
83
84
|
export interface RegisterCollaboratorDto {
|
|
84
85
|
invitationToken: string;
|
|
85
86
|
name: string;
|
|
@@ -87,19 +88,6 @@ export interface RegisterCollaboratorDto {
|
|
|
87
88
|
password: string;
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
export interface SubscriptionPlan {
|
|
91
|
-
id: string;
|
|
92
|
-
name: string;
|
|
93
|
-
price: number;
|
|
94
|
-
billingFrequency: string;
|
|
95
|
-
maxGyms: number;
|
|
96
|
-
maxClientsPerGym: number;
|
|
97
|
-
maxUsersPerGym: number;
|
|
98
|
-
features: any;
|
|
99
|
-
description?: string;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
91
|
export interface InvitationValidationResponse {
|
|
104
92
|
valid: boolean;
|
|
105
93
|
invitation: {
|
|
@@ -117,6 +105,7 @@ export interface InvitationValidationResponse {
|
|
|
117
105
|
}
|
|
118
106
|
|
|
119
107
|
export interface CurrentSessionResponse {
|
|
108
|
+
accessToken: string;
|
|
120
109
|
user: {
|
|
121
110
|
id: string;
|
|
122
111
|
email: string;
|
|
@@ -19,4 +19,20 @@ export interface OrganizationStats {
|
|
|
19
19
|
totalContracts: number;
|
|
20
20
|
activeContracts: number;
|
|
21
21
|
totalRevenue: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface OrganizationWithDetails {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
owner: {
|
|
28
|
+
id: string;
|
|
29
|
+
email: string;
|
|
30
|
+
fullName: string;
|
|
31
|
+
};
|
|
32
|
+
gyms: Array<{
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
address: string;
|
|
36
|
+
}>;
|
|
37
|
+
createdAt: Date;
|
|
22
38
|
}
|
package/src/resources/auth.ts
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
RegisterCollaboratorDto,
|
|
7
7
|
RegisterOwnerDto,
|
|
8
8
|
ResendVerificationDto,
|
|
9
|
-
SubscriptionPlan,
|
|
10
9
|
VerifyEmailDto,
|
|
11
10
|
ChangePasswordDto,
|
|
12
11
|
ChangePasswordResponseDto,
|
|
@@ -19,6 +18,7 @@ import {
|
|
|
19
18
|
ResendResetCodeDto,
|
|
20
19
|
ResendResetCodeResponseDto,
|
|
21
20
|
} from '../models/auth';
|
|
21
|
+
import { SubscriptionPlan } from '../models/subscriptions';
|
|
22
22
|
import { RequestOptions } from '../types';
|
|
23
23
|
import { BaseResource } from './base';
|
|
24
24
|
|
|
@@ -18,8 +18,8 @@ export class OnboardingResource extends BaseResource {
|
|
|
18
18
|
const response = await this.client.post<StartOnboardingResponse>('/onboarding/start', data);
|
|
19
19
|
|
|
20
20
|
// Store tokens after successful onboarding start
|
|
21
|
-
if (response.access_token
|
|
22
|
-
this.client.
|
|
21
|
+
if (response.access_token) {
|
|
22
|
+
this.client.setAuthToken(response.access_token);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
return response;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseResource } from './base';
|
|
2
|
-
import { Organization, UpdateOrganizationDto, OrganizationStats } from '../models/organizations';
|
|
2
|
+
import { Organization, UpdateOrganizationDto, OrganizationStats, OrganizationWithDetails } from '../models/organizations';
|
|
3
3
|
import { RequestOptions } from '../types';
|
|
4
4
|
|
|
5
5
|
export class OrganizationsResource extends BaseResource {
|
|
@@ -20,4 +20,8 @@ export class OrganizationsResource extends BaseResource {
|
|
|
20
20
|
async getOrganizationStats(id: string, options?: RequestOptions): Promise<OrganizationStats> {
|
|
21
21
|
return this.client.get<OrganizationStats>(`${this.basePath}/${id}/stats`, undefined, options);
|
|
22
22
|
}
|
|
23
|
+
|
|
24
|
+
async listOrganizations(options?: RequestOptions): Promise<OrganizationWithDetails[]> {
|
|
25
|
+
return this.client.get<OrganizationWithDetails[]>(`${this.basePath}/list`, undefined, options);
|
|
26
|
+
}
|
|
23
27
|
}
|
package/src/sdk.ts
CHANGED
|
@@ -87,12 +87,6 @@ export class GymSpaceSdk {
|
|
|
87
87
|
this.client.setAuthToken(token);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
/**
|
|
91
|
-
* Set both access and refresh tokens
|
|
92
|
-
*/
|
|
93
|
-
setTokens(accessToken: string, refreshToken: string): void {
|
|
94
|
-
this.client.setTokens(accessToken, refreshToken);
|
|
95
|
-
}
|
|
96
90
|
|
|
97
91
|
/**
|
|
98
92
|
* Set the current gym context
|