@giaeulate/baas-sdk 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.
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Auth Module - Authentication operations
3
+ */
4
+
5
+ import type { HttpClient } from '../http-client';
6
+
7
+ export interface MFASetupResponse {
8
+ secret: string;
9
+ qr_code_url: string;
10
+ recovery_codes: string[];
11
+ }
12
+
13
+ export interface AuthModule {
14
+ login(email: string, password: string): Promise<any>;
15
+ logout(): Promise<void>;
16
+ verifyMFA(mfaToken: string, code: string): Promise<any>;
17
+ verifyMFAWithRecoveryCode(mfaToken: string, recoveryCode: string): Promise<any>;
18
+ setupMFA(): Promise<MFASetupResponse>;
19
+ enableMFA(secret: string, code: string, recoveryCodes?: string[]): Promise<any>;
20
+ disableMFA(code: string): Promise<any>;
21
+ getProfile(): Promise<any>;
22
+ register(email: string, password: string): Promise<any>;
23
+ forgotPassword(email: string): Promise<any>;
24
+ resetPassword(token: string, newPassword: string): Promise<any>;
25
+ validateResetToken(token: string): Promise<any>;
26
+ verifyEmail(token: string): Promise<any>;
27
+ requestEmailVerification(): Promise<any>;
28
+ // OAuth Configuration
29
+ getAuthProviders(): Promise<any>;
30
+ getAuthProvider(provider: string): Promise<any>;
31
+ configureAuthProvider(provider: string, clientID: string, clientSecret: string, enabled: boolean): Promise<any>;
32
+ }
33
+
34
+ export function createAuthModule(client: HttpClient): AuthModule {
35
+ const get = (endpoint: string) => (client as any).get(endpoint);
36
+ const post = (endpoint: string, body?: unknown) => (client as any).post(endpoint, body);
37
+
38
+ return {
39
+ async login(email: string, password: string) {
40
+ const res = await fetch(`${client.url}/api/login`, {
41
+ method: 'POST',
42
+ headers: client.getHeaders(),
43
+ body: JSON.stringify({ email, password }),
44
+ });
45
+
46
+ const contentType = res.headers.get('content-type');
47
+ if (!contentType?.includes('application/json')) {
48
+ throw new Error(`Login failed: Server returned ${res.status}. Please check your connection.`);
49
+ }
50
+
51
+ const data = await res.json().catch(() => {
52
+ throw new Error(`Login failed: Invalid JSON response (status ${res.status})`);
53
+ });
54
+
55
+ if (!res.ok) {
56
+ throw new Error(data?.error || `Login failed: ${res.status}`);
57
+ }
58
+
59
+ if (data.token) {
60
+ client.token = data.token;
61
+ localStorage.setItem('baas_token', data.token);
62
+ }
63
+ return data;
64
+ },
65
+
66
+ async logout() {
67
+ try {
68
+ await post('/api/logout');
69
+ } finally {
70
+ client.token = null;
71
+ localStorage.removeItem('baas_token');
72
+ }
73
+ },
74
+
75
+ async verifyMFA(mfaToken: string, code: string) {
76
+ const data = await post('/api/mfa/finalize', { mfa_token: mfaToken, code });
77
+ if (data.token) {
78
+ client.token = data.token;
79
+ localStorage.setItem('baas_token', data.token);
80
+ }
81
+ return data;
82
+ },
83
+
84
+ async verifyMFAWithRecoveryCode(mfaToken: string, recoveryCode: string) {
85
+ const data = await post('/api/mfa/finalize', { mfa_token: mfaToken, recovery_code: recoveryCode });
86
+ if (data.token) {
87
+ client.token = data.token;
88
+ localStorage.setItem('baas_token', data.token);
89
+ }
90
+ return data;
91
+ },
92
+
93
+ async setupMFA(): Promise<MFASetupResponse> {
94
+ return post('/api/mfa/setup');
95
+ },
96
+
97
+ async enableMFA(secret: string, code: string, recoveryCodes?: string[]) {
98
+ const body: any = { secret, code };
99
+ if (recoveryCodes) {
100
+ body.recovery_codes = recoveryCodes;
101
+ }
102
+ return post('/api/mfa/enable', body);
103
+ },
104
+
105
+ async disableMFA(code: string) {
106
+ return post('/api/mfa/disable', { code });
107
+ },
108
+
109
+ async getProfile() {
110
+ return get('/api/profile');
111
+ },
112
+
113
+ async register(email: string, password: string) {
114
+ const data = await post('/api/register', { email, password });
115
+ if (data.error) {
116
+ throw new Error(data.error);
117
+ }
118
+ return data;
119
+ },
120
+
121
+ async forgotPassword(email: string) {
122
+ return post('/api/auth/forgot-password', { email });
123
+ },
124
+
125
+ async resetPassword(token: string, newPassword: string) {
126
+ return post('/api/auth/reset-password', { token, new_password: newPassword });
127
+ },
128
+
129
+ async validateResetToken(token: string) {
130
+ return get(`/api/auth/validate-reset-token?token=${token}`);
131
+ },
132
+
133
+ async verifyEmail(token: string) {
134
+ return post('/api/auth/verify-email', { token });
135
+ },
136
+
137
+ async requestEmailVerification() {
138
+ return post('/api/auth/request-verification');
139
+ },
140
+
141
+ async getAuthProviders() {
142
+ return get('/api/auth/providers');
143
+ },
144
+
145
+ async getAuthProvider(provider: string) {
146
+ return get(`/api/auth/providers/${provider}`);
147
+ },
148
+
149
+ async configureAuthProvider(provider: string, clientID: string, clientSecret: string, enabled: boolean) {
150
+ return post('/api/auth/providers', {
151
+ provider,
152
+ client_id: clientID,
153
+ client_secret: clientSecret,
154
+ enabled,
155
+ });
156
+ },
157
+ };
158
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Backups Module - Database backup operations
3
+ */
4
+
5
+ import type { HttpClient } from '../http-client';
6
+
7
+ export interface BackupsModule {
8
+ create(options?: { name?: string; tables?: string[] }): Promise<any>;
9
+ list(): Promise<any>;
10
+ get(backupId: string): Promise<any>;
11
+ restore(backupId: string): Promise<any>;
12
+ delete(backupId: string): Promise<any>;
13
+ getDownloadUrl(backupId: string): string;
14
+ listTables(): Promise<any>;
15
+ importFile(formData: FormData): Promise<any>;
16
+ }
17
+
18
+ export function createBackupsModule(client: HttpClient): BackupsModule {
19
+ const get = (endpoint: string) => (client as any).get(endpoint);
20
+ const post = (endpoint: string, body?: unknown) => (client as any).post(endpoint, body);
21
+ const del = (endpoint: string) => (client as any).delete(endpoint);
22
+
23
+ return {
24
+ async create(options?: { name?: string; tables?: string[] }) {
25
+ return post('/api/backups', options || {});
26
+ },
27
+
28
+ async list() {
29
+ return get('/api/backups');
30
+ },
31
+
32
+ async get(backupId: string) {
33
+ return get(`/api/backups/${backupId}`);
34
+ },
35
+
36
+ async restore(backupId: string) {
37
+ return post(`/api/backups/${backupId}/restore`, {});
38
+ },
39
+
40
+ async delete(backupId: string) {
41
+ return del(`/api/backups/${backupId}`);
42
+ },
43
+
44
+ getDownloadUrl(backupId: string) {
45
+ const token = client.getDynamicToken();
46
+ const projectId = client.getDynamicProjectID();
47
+ return `${client.url}/api/backups/${backupId}/download?access_token=${token}&project_id=${projectId}`;
48
+ },
49
+
50
+ async listTables() {
51
+ return get('/api/backups/tables');
52
+ },
53
+
54
+ async importFile(formData: FormData) {
55
+ const headers = client.getHeaders();
56
+ delete headers['Content-Type'];
57
+
58
+ const res = await fetch(`${client.url}/api/import`, {
59
+ method: 'POST',
60
+ headers,
61
+ body: formData,
62
+ });
63
+ const data = await res.json();
64
+ if (!res.ok && res.status === 401) client.forceLogout();
65
+ return data;
66
+ },
67
+ };
68
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Branches Module - Database branches operations
3
+ */
4
+
5
+ import type { HttpClient } from '../http-client';
6
+
7
+ export interface BranchesModule {
8
+ create(input: { name: string; source_branch?: string }): Promise<any>;
9
+ list(): Promise<any>;
10
+ get(id: string): Promise<any>;
11
+ delete(id: string): Promise<any>;
12
+ merge(id: string, targetBranchId: string): Promise<any>;
13
+ reset(id: string): Promise<any>;
14
+ }
15
+
16
+ export function createBranchesModule(client: HttpClient): BranchesModule {
17
+ const get = (endpoint: string) => (client as any).get(endpoint);
18
+ const post = (endpoint: string, body?: unknown) => (client as any).post(endpoint, body);
19
+ const del = (endpoint: string) => (client as any).delete(endpoint);
20
+
21
+ return {
22
+ async create(input: { name: string; source_branch?: string }) {
23
+ return post('/api/branches', input);
24
+ },
25
+
26
+ async list() {
27
+ return get('/api/branches');
28
+ },
29
+
30
+ async get(id: string) {
31
+ return get(`/api/branches/${id}`);
32
+ },
33
+
34
+ async delete(id: string) {
35
+ return del(`/api/branches/${id}`);
36
+ },
37
+
38
+ async merge(id: string, targetBranchId: string) {
39
+ return post(`/api/branches/${id}/merge`, { target_branch_id: targetBranchId });
40
+ },
41
+
42
+ async reset(id: string) {
43
+ return post(`/api/branches/${id}/reset`);
44
+ },
45
+ };
46
+ }
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Database Module - Schema, table, and column operations
3
+ */
4
+
5
+ import type { HttpClient } from '../http-client';
6
+
7
+ export interface DatabaseModule {
8
+ // Schemas
9
+ getSchemas(options?: { search?: string; limit?: number; offset?: number }): Promise<any>;
10
+ getSchema(name: string): Promise<any>;
11
+
12
+ // Tables
13
+ createTable(tableName: string, definition: Record<string, string | { type: string; nullable?: boolean; unique?: boolean; default?: string }>): Promise<any>;
14
+ dropTable(tableName: string): Promise<any>;
15
+ renameTable(tableName: string, newName: string): Promise<any>;
16
+
17
+ // Columns
18
+ addColumn(tableName: string, column: { name: string; type: string; nullable?: boolean; default_value?: string }): Promise<any>;
19
+ dropColumn(tableName: string, columnName: string): Promise<any>;
20
+ modifyColumn(tableName: string, columnName: string, changes: { type: string; nullable?: boolean }): Promise<any>;
21
+ renameColumn(tableName: string, columnName: string, newName: string): Promise<any>;
22
+ setColumnDefault(tableName: string, columnName: string, defaultValue: string | null): Promise<any>;
23
+
24
+ // Foreign Keys
25
+ addForeignKey(tableName: string, fk: { column: string; ref_table: string; ref_column: string; on_delete?: string; on_update?: string }): Promise<any>;
26
+ listForeignKeys(tableName: string): Promise<any>;
27
+ dropForeignKey(tableName: string, constraintName: string): Promise<any>;
28
+
29
+ // Constraints
30
+ addUniqueConstraint(tableName: string, columnName: string): Promise<any>;
31
+ dropConstraint(tableName: string, constraintName: string): Promise<any>;
32
+
33
+ // Data operations
34
+ raw(query: string): Promise<any>;
35
+ queryData(tableName: string, options: { page?: number; limit?: number; filters?: any[] }): Promise<any>;
36
+ downloadExport(tableName: string, format: 'sql' | 'csv' | 'backup', filters?: any[]): Promise<any>;
37
+ }
38
+
39
+ export function createDatabaseModule(client: HttpClient): DatabaseModule {
40
+ const get = (endpoint: string) => (client as any).get(endpoint);
41
+ const post = (endpoint: string, body?: unknown) => (client as any).post(endpoint, body);
42
+ const patch = (endpoint: string, body?: unknown) => (client as any).patch(endpoint, body);
43
+ const del = (endpoint: string) => (client as any).delete(endpoint);
44
+
45
+ return {
46
+ // Schemas
47
+ async getSchemas(options?: { search?: string; limit?: number; offset?: number }) {
48
+ const params = new URLSearchParams();
49
+ if (options?.search) params.append('search', options.search);
50
+ if (options?.limit) params.append('limit', options.limit.toString());
51
+ if (options?.offset) params.append('offset', options.offset.toString());
52
+ const query = params.toString();
53
+ return get(`/api/schemas${query ? `?${query}` : ''}`);
54
+ },
55
+
56
+ async getSchema(name: string) {
57
+ return get(`/api/schemas/${name}`);
58
+ },
59
+
60
+ // Tables
61
+ async createTable(tableName: string, definition: Record<string, string | { type: string; nullable?: boolean; unique?: boolean; default?: string }>) {
62
+ return post('/api/schemas/tables', { table_name: tableName, definition });
63
+ },
64
+
65
+ async dropTable(tableName: string) {
66
+ return del(`/api/schemas/tables/${tableName}`);
67
+ },
68
+
69
+ async renameTable(tableName: string, newName: string) {
70
+ return post(`/api/schemas/tables/${tableName}/rename`, { new_name: newName });
71
+ },
72
+
73
+ // Columns
74
+ async addColumn(tableName: string, column: { name: string; type: string; nullable?: boolean; default_value?: string }) {
75
+ return post(`/api/schemas/tables/${tableName}/columns`, column);
76
+ },
77
+
78
+ async dropColumn(tableName: string, columnName: string) {
79
+ return del(`/api/schemas/tables/${tableName}/columns/${columnName}`);
80
+ },
81
+
82
+ async modifyColumn(tableName: string, columnName: string, changes: { type: string; nullable?: boolean }) {
83
+ return patch(`/api/schemas/tables/${tableName}/columns/${columnName}`, changes);
84
+ },
85
+
86
+ async renameColumn(tableName: string, columnName: string, newName: string) {
87
+ return post(`/api/schemas/tables/${tableName}/columns/${columnName}/rename`, { new_name: newName });
88
+ },
89
+
90
+ async setColumnDefault(tableName: string, columnName: string, defaultValue: string | null) {
91
+ return patch(`/api/schemas/tables/${tableName}/columns/${columnName}/default`, { default_value: defaultValue });
92
+ },
93
+
94
+ // Foreign Keys
95
+ async addForeignKey(tableName: string, fk: { column: string; ref_table: string; ref_column: string; on_delete?: string; on_update?: string }) {
96
+ return post(`/api/schemas/tables/${tableName}/foreign-keys`, fk);
97
+ },
98
+
99
+ async listForeignKeys(tableName: string) {
100
+ return get(`/api/schemas/tables/${tableName}/foreign-keys`);
101
+ },
102
+
103
+ async dropForeignKey(tableName: string, constraintName: string) {
104
+ return del(`/api/schemas/tables/${tableName}/foreign-keys/${constraintName}`);
105
+ },
106
+
107
+ // Constraints
108
+ async addUniqueConstraint(tableName: string, columnName: string) {
109
+ return post(`/api/schemas/tables/${tableName}/constraints/unique`, { column: columnName });
110
+ },
111
+
112
+ async dropConstraint(tableName: string, constraintName: string) {
113
+ return del(`/api/schemas/tables/${tableName}/constraints/${constraintName}`);
114
+ },
115
+
116
+ // Data operations
117
+ async raw(query: string) {
118
+ return post('/api/v1/sql', { query });
119
+ },
120
+
121
+ async queryData(tableName: string, options: { page?: number; limit?: number; filters?: any[] }) {
122
+ const params = new URLSearchParams();
123
+ if (options.page) params.append('page', options.page.toString());
124
+ if (options.limit) params.append('limit', options.limit.toString());
125
+ if (options.filters && options.filters.length > 0) {
126
+ params.append('filters', JSON.stringify(options.filters));
127
+ }
128
+ return get(`/api/v1/data/${tableName}/query?${params.toString()}`);
129
+ },
130
+
131
+ async downloadExport(tableName: string, format: 'sql' | 'csv' | 'backup', filters?: any[]) {
132
+ const params = new URLSearchParams();
133
+ if (filters && filters.length > 0) {
134
+ params.append('filters', JSON.stringify(filters));
135
+ }
136
+
137
+ const res = await fetch(`${client.url}/api/v1/export/${tableName}/${format}?${params.toString()}`, {
138
+ headers: client.getHeaders()
139
+ });
140
+
141
+ if (!res.ok) {
142
+ const data = await res.json();
143
+ return { error: data.error || `Export failed: ${res.status}` };
144
+ }
145
+
146
+ const blob = await res.blob();
147
+ const url = window.URL.createObjectURL(blob);
148
+ const a = document.createElement('a');
149
+ a.href = url;
150
+ a.download = `${tableName}_${new Date().toISOString().split('T')[0]}.${format === 'backup' ? 'dump' : format}`;
151
+ document.body.appendChild(a);
152
+ a.click();
153
+ window.URL.revokeObjectURL(url);
154
+ document.body.removeChild(a);
155
+ return { success: true };
156
+ },
157
+ };
158
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Email Module - Email service operations
3
+ */
4
+
5
+ import type { HttpClient } from '../http-client';
6
+
7
+ export interface EmailConfig {
8
+ provider: string;
9
+ smtp_host?: string;
10
+ smtp_port?: number;
11
+ smtp_user?: string;
12
+ smtp_password?: string;
13
+ sendgrid_api_key?: string;
14
+ resend_api_key?: string;
15
+ from_email: string;
16
+ from_name?: string;
17
+ }
18
+
19
+ export interface EmailTemplate {
20
+ name: string;
21
+ subject: string;
22
+ text_body?: string;
23
+ html_body?: string;
24
+ }
25
+
26
+ export interface SendEmailInput {
27
+ to: string[];
28
+ subject: string;
29
+ text_body?: string;
30
+ html_body?: string;
31
+ template_id?: string;
32
+ template_data?: Record<string, any>;
33
+ }
34
+
35
+ export interface EmailModule {
36
+ send(input: SendEmailInput): Promise<any>;
37
+ getConfig(): Promise<any>;
38
+ saveConfig(config: EmailConfig): Promise<any>;
39
+ createTemplate(template: EmailTemplate): Promise<any>;
40
+ listTemplates(): Promise<any>;
41
+ getTemplate(id: string): Promise<any>;
42
+ updateTemplate(id: string, template: Partial<EmailTemplate>): Promise<any>;
43
+ deleteTemplate(id: string): Promise<any>;
44
+ getLogs(options?: { limit?: number; offset?: number }): Promise<any>;
45
+ }
46
+
47
+ export function createEmailModule(client: HttpClient): EmailModule {
48
+ const get = (endpoint: string) => (client as any).get(endpoint);
49
+ const post = (endpoint: string, body?: unknown) => (client as any).post(endpoint, body);
50
+ const put = (endpoint: string, body?: unknown) => (client as any).put(endpoint, body);
51
+ const del = (endpoint: string) => (client as any).delete(endpoint);
52
+
53
+ return {
54
+ async send(input: SendEmailInput) {
55
+ return post('/api/email/send', input);
56
+ },
57
+
58
+ async getConfig() {
59
+ return get('/api/email/config');
60
+ },
61
+
62
+ async saveConfig(config: EmailConfig) {
63
+ return post('/api/email/config', config);
64
+ },
65
+
66
+ async createTemplate(template: EmailTemplate) {
67
+ return post('/api/email/templates', template);
68
+ },
69
+
70
+ async listTemplates() {
71
+ return get('/api/email/templates');
72
+ },
73
+
74
+ async getTemplate(id: string) {
75
+ return get(`/api/email/templates/${id}`);
76
+ },
77
+
78
+ async updateTemplate(id: string, template: Partial<EmailTemplate>) {
79
+ return put(`/api/email/templates/${id}`, template);
80
+ },
81
+
82
+ async deleteTemplate(id: string) {
83
+ return del(`/api/email/templates/${id}`);
84
+ },
85
+
86
+ async getLogs(options?: { limit?: number; offset?: number }) {
87
+ const params = new URLSearchParams();
88
+ if (options?.limit) params.set('limit', options.limit.toString());
89
+ if (options?.offset) params.set('offset', options.offset.toString());
90
+ return get(`/api/email/logs?${params.toString()}`);
91
+ },
92
+ };
93
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Environment Variables Module
3
+ */
4
+
5
+ import type { HttpClient } from '../http-client';
6
+
7
+ export interface EnvVarsModule {
8
+ create(input: { key: string; value: string; is_secret?: boolean }): Promise<any>;
9
+ list(): Promise<any>;
10
+ get(id: string): Promise<any>;
11
+ update(id: string, value: string): Promise<any>;
12
+ delete(id: string): Promise<any>;
13
+ }
14
+
15
+ export function createEnvVarsModule(client: HttpClient): EnvVarsModule {
16
+ const get = (endpoint: string) => (client as any).get(endpoint);
17
+ const post = (endpoint: string, body?: unknown) => (client as any).post(endpoint, body);
18
+ const put = (endpoint: string, body?: unknown) => (client as any).put(endpoint, body);
19
+ const del = (endpoint: string) => (client as any).delete(endpoint);
20
+
21
+ return {
22
+ async create(input: { key: string; value: string; is_secret?: boolean }) {
23
+ return post('/api/env-vars', input);
24
+ },
25
+
26
+ async list() {
27
+ return get('/api/env-vars');
28
+ },
29
+
30
+ async get(id: string) {
31
+ return get(`/api/env-vars/${id}`);
32
+ },
33
+
34
+ async update(id: string, value: string) {
35
+ return put(`/api/env-vars/${id}`, { value });
36
+ },
37
+
38
+ async delete(id: string) {
39
+ return del(`/api/env-vars/${id}`);
40
+ },
41
+ };
42
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Functions Module - Edge function operations
3
+ */
4
+
5
+ import type { HttpClient } from '../http-client';
6
+
7
+ export interface FunctionsModule {
8
+ invoke(id: string, data?: any): Promise<any>;
9
+ list(): Promise<any>;
10
+ create(name: string, code: string): Promise<any>;
11
+ delete(id: string): Promise<any>;
12
+ update(id: string, code: string): Promise<any>;
13
+
14
+ // Hooks
15
+ listHooks(): Promise<any>;
16
+ createHook(data: {
17
+ event_type: string,
18
+ function_id: string,
19
+ table_name?: string,
20
+ config?: any
21
+ }): Promise<any>;
22
+ deleteHook(id: string): Promise<any>;
23
+ }
24
+
25
+ export function createFunctionsModule(client: HttpClient): FunctionsModule {
26
+ const post = (endpoint: string, body?: unknown) => (client as any).post(endpoint, body);
27
+ const get = (endpoint: string) => (client as any).get(endpoint);
28
+ const del = (endpoint: string) => (client as any).delete(endpoint);
29
+ const put = (endpoint: string, body?: unknown) => (client as any).put(endpoint, body);
30
+
31
+ return {
32
+ async invoke(id: string, data: any = {}) {
33
+ return post(`/api/functions/${id}/execute`, data);
34
+ },
35
+ async list() {
36
+ return get('/api/functions');
37
+ },
38
+ async create(name: string, code: string) {
39
+ return post('/api/functions', { name, code });
40
+ },
41
+ async delete(id: string) {
42
+ return del(`/api/functions/${id}`);
43
+ },
44
+ async update(id: string, code: string) {
45
+ return put(`/api/functions/${id}`, { code });
46
+ },
47
+ async listHooks() {
48
+ return get('/api/hooks');
49
+ },
50
+ async createHook(data: any) {
51
+ return post('/api/hooks', data);
52
+ },
53
+ async deleteHook(id: string) {
54
+ return del(`/api/hooks/${id}`);
55
+ },
56
+ };
57
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * GraphQL Module
3
+ */
4
+
5
+ import type { HttpClient } from '../http-client';
6
+
7
+ export interface GraphQLModule {
8
+ query(query: string, variables?: Record<string, any>): Promise<any>;
9
+ getPlaygroundUrl(): string;
10
+ }
11
+
12
+ export function createGraphQLModule(client: HttpClient): GraphQLModule {
13
+ const post = (endpoint: string, body?: unknown) => (client as any).post(endpoint, body);
14
+
15
+ return {
16
+ async query(query: string, variables?: Record<string, any>) {
17
+ return post('/api/graphql', { query, variables });
18
+ },
19
+
20
+ getPlaygroundUrl() {
21
+ return `${client.url}/api/graphql/playground`;
22
+ },
23
+ };
24
+ }