@gymspace/sdk 1.2.5 → 1.2.9

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.
@@ -1,10 +1,10 @@
1
1
  import { BaseResource } from './base';
2
- import {
3
- Contract,
4
- CreateContractDto,
5
- RenewContractDto,
2
+ import {
3
+ Contract,
4
+ CreateContractDto,
5
+ RenewContractDto,
6
6
  FreezeContractDto,
7
- GetContractsParams
7
+ GetContractsParams,
8
8
  } from '../models/contracts';
9
9
  import { RequestOptions, PaginatedResponseDto } from '../types';
10
10
 
@@ -17,7 +17,7 @@ export class ContractsResource extends BaseResource {
17
17
 
18
18
  async getGymContracts(
19
19
  params?: GetContractsParams,
20
- options?: RequestOptions
20
+ options?: RequestOptions,
21
21
  ): Promise<PaginatedResponseDto<Contract>> {
22
22
  return this.paginate<Contract>(this.basePath, params, options);
23
23
  }
@@ -26,21 +26,14 @@ export class ContractsResource extends BaseResource {
26
26
  return this.client.get<Contract>(`${this.basePath}/${id}`, undefined, options);
27
27
  }
28
28
 
29
- async getClientContracts(
30
- clientId: string,
31
- options?: RequestOptions
32
- ): Promise<Contract[]> {
33
- return this.client.get<Contract[]>(
34
- `${this.basePath}/client/${clientId}`,
35
- undefined,
36
- options
37
- );
29
+ async getClientContracts(clientId: string, options?: RequestOptions): Promise<Contract[]> {
30
+ return this.client.get<Contract[]>(`${this.basePath}/client/${clientId}`, undefined, options);
38
31
  }
39
32
 
40
33
  async renewContract(
41
34
  id: string,
42
35
  data: RenewContractDto,
43
- options?: RequestOptions
36
+ options?: RequestOptions,
44
37
  ): Promise<Contract> {
45
38
  return this.client.post<Contract>(`${this.basePath}/${id}/renew`, data, options);
46
39
  }
@@ -48,12 +41,27 @@ export class ContractsResource extends BaseResource {
48
41
  async freezeContract(
49
42
  id: string,
50
43
  data: FreezeContractDto,
51
- options?: RequestOptions
44
+ options?: RequestOptions,
52
45
  ): Promise<Contract> {
53
46
  return this.client.post<Contract>(`${this.basePath}/${id}/freeze`, data, options);
54
47
  }
55
48
 
56
- async cancelContract(id: string, data: { reason: string }, options?: RequestOptions): Promise<Contract> {
49
+ async cancelContract(
50
+ id: string,
51
+ data: { reason: string },
52
+ options?: RequestOptions,
53
+ ): Promise<Contract> {
57
54
  return this.client.put<Contract>(`${this.basePath}/${id}/cancel`, data, options);
58
55
  }
59
- }
56
+
57
+ async resendWhatsAppNotification(
58
+ contractId: string,
59
+ options?: RequestOptions,
60
+ ): Promise<{ success: boolean; message: string }> {
61
+ return this.client.post<{ success: boolean; message: string }>(
62
+ `${this.basePath}/${contractId}/resend-whatsapp`,
63
+ {},
64
+ options,
65
+ );
66
+ }
67
+ }
@@ -8,6 +8,7 @@ import {
8
8
  CheckIns,
9
9
  NewClients,
10
10
  DateRangeParams,
11
+ CheckInsList,
11
12
  } from '../models/dashboard';
12
13
 
13
14
  export class DashboardResource extends BaseResource {
@@ -79,4 +80,13 @@ export class DashboardResource extends BaseResource {
79
80
  ...params,
80
81
  });
81
82
  }
82
- }
83
+
84
+ /**
85
+ * Get detailed list of check-ins within date range
86
+ * @param params Optional date range parameters (defaults to current day)
87
+ * @returns Detailed list of check-ins with client and registeredBy information
88
+ */
89
+ async getCheckInsList(params?: DateRangeParams): Promise<CheckInsList> {
90
+ return this.client.get<CheckInsList>('/dashboard/check-ins/list', params);
91
+ }
92
+ }
@@ -23,4 +23,6 @@ export * from './users';
23
23
  export * from './subscriptions';
24
24
  export * from './subscription-plans';
25
25
  export * from './admin-subscription-management';
26
- export * from './payment-methods';
26
+ export * from './payment-methods';
27
+ export * from './whatsapp';
28
+ export * from './whatsapp-templates';
@@ -1,45 +1,42 @@
1
1
  import { BaseResource } from './base';
2
- import {
2
+ import type {
3
3
  Invitation,
4
4
  CreateInvitationDto,
5
5
  AcceptInvitationDto,
6
6
  ValidateByCodeDto,
7
- GetGymInvitationsParams
8
- } from '../models/invitations';
7
+ } from '@gymspace/shared';
9
8
  import { RequestOptions } from '../types';
10
9
 
10
+ export interface GetGymInvitationsParams {
11
+ gymId: string;
12
+ }
13
+
11
14
  export class InvitationsResource extends BaseResource {
12
15
  private basePath = 'invitations';
13
16
 
14
- async createInvitation(
15
- data: CreateInvitationDto,
16
- options?: RequestOptions
17
- ): Promise<Invitation> {
17
+ async createInvitation(data: CreateInvitationDto, options?: RequestOptions): Promise<Invitation> {
18
18
  return this.client.post<Invitation>(this.basePath, data, options);
19
19
  }
20
20
 
21
21
  async getGymInvitations(
22
22
  params: GetGymInvitationsParams,
23
- options?: RequestOptions
23
+ options?: RequestOptions,
24
24
  ): Promise<Invitation[]> {
25
25
  return this.client.get<Invitation[]>(this.basePath, params, options);
26
26
  }
27
27
 
28
28
  async validateByCode(
29
29
  data: ValidateByCodeDto,
30
- options?: RequestOptions
30
+ options?: RequestOptions,
31
31
  ): Promise<{ email: string; gymName: string; roleName: string; token: string }> {
32
32
  return this.client.post(`${this.basePath}/validate-by-code`, data, options);
33
33
  }
34
34
 
35
- async acceptInvitation(
36
- data: AcceptInvitationDto,
37
- options?: RequestOptions
38
- ): Promise<void> {
35
+ async acceptInvitation(data: AcceptInvitationDto, options?: RequestOptions): Promise<void> {
39
36
  return this.client.post<void>(`${this.basePath}/accept`, data, options);
40
37
  }
41
38
 
42
39
  async cancelInvitation(id: string, options?: RequestOptions): Promise<void> {
43
40
  return this.client.put<void>(`${this.basePath}/${id}/cancel`, undefined, options);
44
41
  }
45
- }
42
+ }
@@ -1,5 +1,6 @@
1
1
  import { BaseResource } from './base';
2
- import { Role, PermissionsGroup } from '../models/roles';
2
+ import type { Role } from '@gymspace/shared';
3
+ import type { PermissionsGroup } from '../models/roles';
3
4
  import { RequestOptions } from '../types';
4
5
 
5
6
  export class RolesResource extends BaseResource {
@@ -8,7 +8,7 @@ import {
8
8
  SearchSalesParams,
9
9
  SalesStats,
10
10
  TopSellingProduct,
11
- CustomerSalesReport
11
+ CustomerSalesReport,
12
12
  } from '../models/sales';
13
13
  import { RequestOptions, PaginatedResponseDto } from '../types';
14
14
 
@@ -21,7 +21,7 @@ export class SalesResource extends BaseResource {
21
21
 
22
22
  async searchSales(
23
23
  params?: SearchSalesParams,
24
- options?: RequestOptions
24
+ options?: RequestOptions,
25
25
  ): Promise<PaginatedResponseDto<Sale>> {
26
26
  return this.paginate<Sale>(this.basePath, params, options);
27
27
  }
@@ -30,27 +30,23 @@ export class SalesResource extends BaseResource {
30
30
  return this.client.get<Sale>(`${this.basePath}/${id}`, undefined, options);
31
31
  }
32
32
 
33
- async updateSale(
34
- id: string,
35
- data: UpdateSaleDto,
36
- options?: RequestOptions
37
- ): Promise<Sale> {
33
+ async updateSale(id: string, data: UpdateSaleDto, options?: RequestOptions): Promise<Sale> {
38
34
  return this.client.put<Sale>(`${this.basePath}/${id}`, data, options);
39
35
  }
40
36
 
41
37
  async updatePaymentStatus(
42
38
  id: string,
43
39
  paymentStatus: 'paid' | 'unpaid',
44
- options?: RequestOptions
40
+ options?: RequestOptions,
45
41
  ): Promise<Sale> {
46
- return this.client.put<Sale>(`${this.basePath}/${id}/payment-status`, { paymentStatus }, options);
42
+ return this.client.put<Sale>(
43
+ `${this.basePath}/${id}/payment-status`,
44
+ { paymentStatus },
45
+ options,
46
+ );
47
47
  }
48
48
 
49
- async paySale(
50
- id: string,
51
- data: PaySaleDto,
52
- options?: RequestOptions
53
- ): Promise<Sale> {
49
+ async paySale(id: string, data: PaySaleDto, options?: RequestOptions): Promise<Sale> {
54
50
  return this.client.post<Sale>(`${this.basePath}/${id}/payment`, data, options);
55
51
  }
56
52
 
@@ -61,7 +57,7 @@ export class SalesResource extends BaseResource {
61
57
  async getSalesStats(
62
58
  startDate?: string,
63
59
  endDate?: string,
64
- options?: RequestOptions
60
+ options?: RequestOptions,
65
61
  ): Promise<SalesStats> {
66
62
  const params: Record<string, string> = {};
67
63
  if (startDate) params.startDate = startDate;
@@ -70,7 +66,7 @@ export class SalesResource extends BaseResource {
70
66
  return this.client.get<SalesStats>(
71
67
  `${this.basePath}/stats`,
72
68
  Object.keys(params).length > 0 ? params : undefined,
73
- options
69
+ options,
74
70
  );
75
71
  }
76
72
 
@@ -78,23 +74,19 @@ export class SalesResource extends BaseResource {
78
74
  limit: number = 10,
79
75
  startDate?: string,
80
76
  endDate?: string,
81
- options?: RequestOptions
77
+ options?: RequestOptions,
82
78
  ): Promise<TopSellingProduct[]> {
83
79
  const params: Record<string, string | number> = { limit };
84
80
  if (startDate) params.startDate = startDate;
85
81
  if (endDate) params.endDate = endDate;
86
82
 
87
- return this.client.get<TopSellingProduct[]>(
88
- `${this.basePath}/top-products`,
89
- params,
90
- options
91
- );
83
+ return this.client.get<TopSellingProduct[]>(`${this.basePath}/top-products`, params, options);
92
84
  }
93
85
 
94
86
  async getSalesByCustomer(
95
87
  startDate?: string,
96
88
  endDate?: string,
97
- options?: RequestOptions
89
+ options?: RequestOptions,
98
90
  ): Promise<CustomerSalesReport> {
99
91
  const params: Record<string, string> = {};
100
92
  if (startDate) params.startDate = startDate;
@@ -103,7 +95,18 @@ export class SalesResource extends BaseResource {
103
95
  return this.client.get<CustomerSalesReport>(
104
96
  `${this.basePath}/reports/by-customer`,
105
97
  Object.keys(params).length > 0 ? params : undefined,
106
- options
98
+ options,
99
+ );
100
+ }
101
+
102
+ async resendWhatsAppNotification(
103
+ saleId: string,
104
+ options?: RequestOptions,
105
+ ): Promise<{ success: boolean; message: string }> {
106
+ return this.client.post<{ success: boolean; message: string }>(
107
+ `${this.basePath}/${saleId}/resend-whatsapp`,
108
+ {},
109
+ options,
107
110
  );
108
111
  }
109
- }
112
+ }
@@ -0,0 +1,80 @@
1
+ import { BaseResource } from './base';
2
+ import {
3
+ WhatsAppTemplate,
4
+ CreateTemplateDto,
5
+ UpdateTemplateDto,
6
+ SearchTemplatesDto,
7
+ PreviewTemplateResponse,
8
+ } from '../models/whatsapp';
9
+ import { RequestOptions, PaginatedResponseDto } from '../types';
10
+
11
+ // Import TemplateCode type from shared (re-exported via types)
12
+ type TemplateCode = string;
13
+
14
+ export class WhatsAppTemplatesResource extends BaseResource {
15
+ private basePath = 'whatsapp/templates';
16
+
17
+ /**
18
+ * Create a new WhatsApp template
19
+ */
20
+ async create(data: CreateTemplateDto, options?: RequestOptions): Promise<WhatsAppTemplate> {
21
+ return this.client.post<WhatsAppTemplate>(this.basePath, data, options);
22
+ }
23
+
24
+ /**
25
+ * Get all WhatsApp templates with pagination and filters
26
+ */
27
+ async findAll(
28
+ params?: SearchTemplatesDto,
29
+ options?: RequestOptions,
30
+ ): Promise<PaginatedResponseDto<WhatsAppTemplate>> {
31
+ return this.paginate<WhatsAppTemplate>(this.basePath, params, options);
32
+ }
33
+
34
+ /**
35
+ * Get a specific WhatsApp template by ID
36
+ */
37
+ async findOne(id: string, options?: RequestOptions): Promise<WhatsAppTemplate> {
38
+ return this.client.get<WhatsAppTemplate>(`${this.basePath}/${id}`, undefined, options);
39
+ }
40
+
41
+ /**
42
+ * Get a WhatsApp template by code
43
+ */
44
+ async findByCode(code: TemplateCode, options?: RequestOptions): Promise<WhatsAppTemplate> {
45
+ return this.client.get<WhatsAppTemplate>(`${this.basePath}/code/${code}`, undefined, options);
46
+ }
47
+
48
+ /**
49
+ * Update a WhatsApp template
50
+ */
51
+ async update(
52
+ id: string,
53
+ data: UpdateTemplateDto,
54
+ options?: RequestOptions,
55
+ ): Promise<WhatsAppTemplate> {
56
+ return this.client.put<WhatsAppTemplate>(`${this.basePath}/${id}`, data, options);
57
+ }
58
+
59
+ /**
60
+ * Delete a WhatsApp template
61
+ */
62
+ async remove(id: string, options?: RequestOptions): Promise<void> {
63
+ return this.client.delete<void>(`${this.basePath}/${id}`, options);
64
+ }
65
+
66
+ /**
67
+ * Preview a template with variables
68
+ */
69
+ async preview(
70
+ id: string,
71
+ variables: Record<string, any>,
72
+ options?: RequestOptions,
73
+ ): Promise<PreviewTemplateResponse> {
74
+ return this.client.post<PreviewTemplateResponse>(
75
+ `${this.basePath}/${id}/preview`,
76
+ variables,
77
+ options,
78
+ );
79
+ }
80
+ }
@@ -0,0 +1,97 @@
1
+ import { BaseResource } from './base';
2
+ import {
3
+ WhatsAppConfig,
4
+ WhatsAppMessage,
5
+ CreateWhatsAppConfigDto,
6
+ UpdateWhatsAppConfigDto,
7
+ SendWhatsAppMessageDto,
8
+ SearchWhatsAppMessagesDto,
9
+ ConnectionStatusResponse,
10
+ InitializeConnectionResponse,
11
+ Contact,
12
+ DisconnectResponse,
13
+ } from '../models/whatsapp';
14
+ import { RequestOptions, PaginatedResponseDto } from '../types';
15
+
16
+ export class WhatsAppResource extends BaseResource {
17
+ private basePath = 'whatsapp';
18
+
19
+ /**
20
+ * Get WhatsApp configuration for the current gym
21
+ */
22
+ async getConfig(options?: RequestOptions): Promise<WhatsAppConfig> {
23
+ return this.client.get<WhatsAppConfig>(`${this.basePath}/config`, undefined, options);
24
+ }
25
+
26
+ /**
27
+ * Initialize WhatsApp connection
28
+ * Returns QR code if needed
29
+ */
30
+ async initializeConnection(options?: RequestOptions): Promise<InitializeConnectionResponse> {
31
+ return this.client.post<InitializeConnectionResponse>(
32
+ `${this.basePath}/initialize`,
33
+ {},
34
+ options,
35
+ );
36
+ }
37
+
38
+ /**
39
+ * Update WhatsApp configuration
40
+ */
41
+ async updateConfig(
42
+ data: UpdateWhatsAppConfigDto,
43
+ options?: RequestOptions,
44
+ ): Promise<WhatsAppConfig> {
45
+ return this.client.put<WhatsAppConfig>(`${this.basePath}/config`, data, options);
46
+ }
47
+
48
+ /**
49
+ * Get WhatsApp connection status
50
+ */
51
+ async getConnectionStatus(options?: RequestOptions): Promise<ConnectionStatusResponse> {
52
+ return this.client.get<ConnectionStatusResponse>(
53
+ `${this.basePath}/connection-status`,
54
+ undefined,
55
+ options,
56
+ );
57
+ }
58
+
59
+ /**
60
+ * Send a WhatsApp message
61
+ */
62
+ async sendMessage(
63
+ data: SendWhatsAppMessageDto,
64
+ options?: RequestOptions,
65
+ ): Promise<WhatsAppMessage> {
66
+ return this.client.post<WhatsAppMessage>(`${this.basePath}/send-message`, data, options);
67
+ }
68
+
69
+ /**
70
+ * Get WhatsApp messages with pagination and filters
71
+ */
72
+ async getMessages(
73
+ params?: SearchWhatsAppMessagesDto,
74
+ options?: RequestOptions,
75
+ ): Promise<PaginatedResponseDto<WhatsAppMessage>> {
76
+ return this.paginate<WhatsAppMessage>(`${this.basePath}/messages`, params, options);
77
+ }
78
+
79
+ /**
80
+ * Get a specific WhatsApp message by ID
81
+ */
82
+ async getMessage(id: string, options?: RequestOptions): Promise<WhatsAppMessage> {
83
+ return this.client.get<WhatsAppMessage>(`${this.basePath}/messages/${id}`, undefined, options);
84
+ }
85
+
86
+ async listContacts(options?: RequestOptions): Promise<Contact[]> {
87
+ return this.client.get<Contact[]>(`${this.basePath}/contacts`, undefined, options);
88
+ }
89
+
90
+ /**
91
+ * Disconnect WhatsApp instance
92
+ * Logs out from WhatsApp without deleting the instance
93
+ */
94
+ async disconnect(options?: RequestOptions): Promise<DisconnectResponse> {
95
+ return this.client.post<DisconnectResponse>(`${this.basePath}/disconnect`, {}, options);
96
+ }
97
+ }
package/src/sdk.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { ApiClient } from './client';
2
2
  import { GymSpaceConfig } from './types';
3
+ import { createAgentFetch } from './utils/agent-fetch';
3
4
  import {
4
5
  AuthResource,
5
6
  OrganizationsResource,
@@ -27,11 +28,14 @@ import {
27
28
  SubscriptionPlansResource,
28
29
  AdminSubscriptionManagementResource,
29
30
  PaymentMethodsResource,
31
+ WhatsAppResource,
32
+ WhatsAppTemplatesResource,
30
33
  } from './resources';
31
34
 
32
35
  export class GymSpaceSdk {
33
36
  public client: ApiClient;
34
-
37
+ private expoFetch?: typeof globalThis.fetch;
38
+
35
39
  // Resources
36
40
  public auth: AuthResource;
37
41
  public organizations: OrganizationsResource;
@@ -59,10 +63,12 @@ export class GymSpaceSdk {
59
63
  public subscriptionPlans: SubscriptionPlansResource;
60
64
  public adminSubscriptionManagement: AdminSubscriptionManagementResource;
61
65
  public paymentMethods: PaymentMethodsResource;
66
+ public whatsapp: WhatsAppResource;
67
+ public whatsappTemplates: WhatsAppTemplatesResource;
62
68
 
63
69
  constructor(config: GymSpaceConfig) {
64
70
  this.client = new ApiClient(config);
65
-
71
+
66
72
  // Initialize resources
67
73
  this.auth = new AuthResource(this.client);
68
74
  this.organizations = new OrganizationsResource(this.client);
@@ -90,6 +96,8 @@ export class GymSpaceSdk {
90
96
  this.subscriptionPlans = new SubscriptionPlansResource(this.client);
91
97
  this.adminSubscriptionManagement = new AdminSubscriptionManagementResource(this.client);
92
98
  this.paymentMethods = new PaymentMethodsResource(this.client);
99
+ this.whatsapp = new WhatsAppResource(this.client);
100
+ this.whatsappTemplates = new WhatsAppTemplatesResource(this.client);
93
101
  }
94
102
 
95
103
  /**
@@ -127,10 +135,27 @@ export class GymSpaceSdk {
127
135
  this.client.clearAuth();
128
136
  }
129
137
 
138
+ /**
139
+ * Set Expo fetch for React Native environments
140
+ * Should be called once during app initialization
141
+ */
142
+ setExpoFetch(fetchFn: typeof globalThis.fetch): void {
143
+ this.expoFetch = fetchFn;
144
+ }
145
+
146
+ /**
147
+ * Create a fetch function for agent endpoints
148
+ * Uses the /agent/* proxy that includes request context
149
+ * Automatically uses Expo fetch if set
150
+ */
151
+ createAgentFetch() {
152
+ return createAgentFetch(this.client, this.expoFetch);
153
+ }
154
+
130
155
  /**
131
156
  * Get the underlying API client
132
157
  */
133
158
  getClient(): ApiClient {
134
159
  return this.client;
135
160
  }
136
- }
161
+ }
package/src/types.ts CHANGED
@@ -37,5 +37,5 @@ import type { PaginationParams as SharedPaginationParams } from '@gymspace/share
37
37
  // Re-export as PaginationQueryDto for backward compatibility
38
38
  export type PaginationQueryDto = SharedPaginationParams;
39
39
 
40
- // Re-export shared types
41
- export * from '@gymspace/shared';
40
+ // Re-export shared types (including constants and enums)
41
+ export * from '@gymspace/shared';
@@ -0,0 +1,25 @@
1
+ import { ApiClient } from '../client';
2
+
3
+ export function createAgentFetch(apiClient: ApiClient, customFetch?: typeof globalThis.fetch) {
4
+ const fetchFn = customFetch || fetch;
5
+
6
+ return async (path: string, options?: RequestInit) => {
7
+ const fullUrl = `${apiClient.getBaseUrl()}/agent${path}`;
8
+
9
+ // Get gymId from axios instance headers
10
+ const axiosInstance = (apiClient as any).axiosInstance;
11
+ const gymId = axiosInstance?.defaults?.headers?.common?.['X-Gym-Id'];
12
+
13
+ const headers = {
14
+ 'Content-Type': 'application/json',
15
+ ...(apiClient.getAccessToken() && { Authorization: `Bearer ${apiClient.getAccessToken()}` }),
16
+ ...(gymId && { 'X-Gym-Id': gymId }),
17
+ ...(options?.headers || {}),
18
+ };
19
+
20
+ return fetchFn(fullUrl, {
21
+ ...options,
22
+ headers,
23
+ });
24
+ };
25
+ }