@gymspace/sdk 1.2.4 → 1.2.8

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.
@@ -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,9 +1,12 @@
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,
6
7
  GymsResource,
8
+ CollaboratorsResource,
9
+ RolesResource,
7
10
  ClientsResource,
8
11
  MembershipPlansResource,
9
12
  ContractsResource,
@@ -25,15 +28,20 @@ import {
25
28
  SubscriptionPlansResource,
26
29
  AdminSubscriptionManagementResource,
27
30
  PaymentMethodsResource,
31
+ WhatsAppResource,
32
+ WhatsAppTemplatesResource,
28
33
  } from './resources';
29
34
 
30
35
  export class GymSpaceSdk {
31
36
  public client: ApiClient;
32
-
37
+ private expoFetch?: typeof globalThis.fetch;
38
+
33
39
  // Resources
34
40
  public auth: AuthResource;
35
41
  public organizations: OrganizationsResource;
36
42
  public gyms: GymsResource;
43
+ public collaborators: CollaboratorsResource;
44
+ public roles: RolesResource;
37
45
  public clients: ClientsResource;
38
46
  public membershipPlans: MembershipPlansResource;
39
47
  public contracts: ContractsResource;
@@ -55,14 +63,18 @@ export class GymSpaceSdk {
55
63
  public subscriptionPlans: SubscriptionPlansResource;
56
64
  public adminSubscriptionManagement: AdminSubscriptionManagementResource;
57
65
  public paymentMethods: PaymentMethodsResource;
66
+ public whatsapp: WhatsAppResource;
67
+ public whatsappTemplates: WhatsAppTemplatesResource;
58
68
 
59
69
  constructor(config: GymSpaceConfig) {
60
70
  this.client = new ApiClient(config);
61
-
71
+
62
72
  // Initialize resources
63
73
  this.auth = new AuthResource(this.client);
64
74
  this.organizations = new OrganizationsResource(this.client);
65
75
  this.gyms = new GymsResource(this.client);
76
+ this.collaborators = new CollaboratorsResource(this.client);
77
+ this.roles = new RolesResource(this.client);
66
78
  this.clients = new ClientsResource(this.client);
67
79
  this.membershipPlans = new MembershipPlansResource(this.client);
68
80
  this.contracts = new ContractsResource(this.client);
@@ -84,6 +96,8 @@ export class GymSpaceSdk {
84
96
  this.subscriptionPlans = new SubscriptionPlansResource(this.client);
85
97
  this.adminSubscriptionManagement = new AdminSubscriptionManagementResource(this.client);
86
98
  this.paymentMethods = new PaymentMethodsResource(this.client);
99
+ this.whatsapp = new WhatsAppResource(this.client);
100
+ this.whatsappTemplates = new WhatsAppTemplatesResource(this.client);
87
101
  }
88
102
 
89
103
  /**
@@ -121,10 +135,27 @@ export class GymSpaceSdk {
121
135
  this.client.clearAuth();
122
136
  }
123
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
+
124
155
  /**
125
156
  * Get the underlying API client
126
157
  */
127
158
  getClient(): ApiClient {
128
159
  return this.client;
129
160
  }
130
- }
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
+ }