@giaeulate/baas-sdk 1.0.0 → 1.0.2
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/package.json +1 -1
- package/src/client.ts +13 -11
- package/src/http-client.ts +30 -29
- package/src/index.ts +0 -1
- package/src/modules/backups.ts +1 -2
- package/src/modules/environments.ts +59 -0
- package/src/modules/realtime.ts +1 -1
- package/src/realtime.ts +4 -4
- package/src/modules/projects.ts +0 -25
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -12,7 +12,6 @@ import { RealtimeAction, RealtimeCallback } from './types';
|
|
|
12
12
|
// Module imports
|
|
13
13
|
import { createAuthModule, type AuthModule } from './modules/auth';
|
|
14
14
|
import { createUsersModule, type UsersModule } from './modules/users';
|
|
15
|
-
import { createProjectsModule, type ProjectsModule } from './modules/projects';
|
|
16
15
|
import { createDatabaseModule, type DatabaseModule } from './modules/database';
|
|
17
16
|
import { createStorageModule, type StorageModule } from './modules/storage';
|
|
18
17
|
import { createBackupsModule, type BackupsModule } from './modules/backups';
|
|
@@ -30,6 +29,7 @@ import { createLogDrainsModule, type LogDrainsModule } from './modules/log-drain
|
|
|
30
29
|
import { createBranchesModule, type BranchesModule } from './modules/branches';
|
|
31
30
|
import { createRealtimeModule, type RealtimeModule } from './modules/realtime';
|
|
32
31
|
import { createApiKeysModule, type ApiKeysModule } from './modules/api-keys';
|
|
32
|
+
import { createEnvironmentsModule, type EnvironmentsModule } from './modules/environments';
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* Main BaaS Client - Composes all feature modules
|
|
@@ -52,7 +52,6 @@ export class BaasClient extends HttpClient {
|
|
|
52
52
|
// Feature modules
|
|
53
53
|
public readonly auth: AuthModule;
|
|
54
54
|
public readonly users: UsersModule;
|
|
55
|
-
public readonly projects: ProjectsModule;
|
|
56
55
|
public readonly database: DatabaseModule;
|
|
57
56
|
public readonly storage: StorageModule;
|
|
58
57
|
public readonly backups: BackupsModule;
|
|
@@ -70,14 +69,14 @@ export class BaasClient extends HttpClient {
|
|
|
70
69
|
public readonly branches: BranchesModule;
|
|
71
70
|
public readonly realtime: RealtimeModule;
|
|
72
71
|
public readonly apiKeys: ApiKeysModule;
|
|
72
|
+
public readonly environments: EnvironmentsModule;
|
|
73
73
|
|
|
74
|
-
constructor(url?: string,
|
|
75
|
-
super(url,
|
|
74
|
+
constructor(url?: string, apiKey?: string) {
|
|
75
|
+
super(url, apiKey);
|
|
76
76
|
|
|
77
77
|
// Initialize all modules with this client instance
|
|
78
78
|
this.auth = createAuthModule(this);
|
|
79
79
|
this.users = createUsersModule(this);
|
|
80
|
-
this.projects = createProjectsModule(this);
|
|
81
80
|
this.database = createDatabaseModule(this);
|
|
82
81
|
this.storage = createStorageModule(this);
|
|
83
82
|
this.backups = createBackupsModule(this);
|
|
@@ -95,6 +94,7 @@ export class BaasClient extends HttpClient {
|
|
|
95
94
|
this.branches = createBranchesModule(this);
|
|
96
95
|
this.realtime = createRealtimeModule(this);
|
|
97
96
|
this.apiKeys = createApiKeysModule(this);
|
|
97
|
+
this.environments = createEnvironmentsModule(this);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
/**
|
|
@@ -130,10 +130,6 @@ export class BaasClient extends HttpClient {
|
|
|
130
130
|
async updateUser(id: string, updates: any) { return this.users.update(id, updates); }
|
|
131
131
|
async deleteUser(id: string) { return this.users.delete(id); }
|
|
132
132
|
|
|
133
|
-
// Projects shortcuts
|
|
134
|
-
async listProjects() { return this.projects.list(); }
|
|
135
|
-
async createProject(name: string) { return this.projects.create(name); }
|
|
136
|
-
|
|
137
133
|
// Database shortcuts
|
|
138
134
|
async raw(query: string) { return this.database.raw(query); }
|
|
139
135
|
async getSchemas(options?: any) { return this.database.getSchemas(options); }
|
|
@@ -257,7 +253,13 @@ export class BaasClient extends HttpClient {
|
|
|
257
253
|
async getAuditActions() { return this.audit.getActions(); }
|
|
258
254
|
|
|
259
255
|
// Realtime shortcuts
|
|
260
|
-
subscribe<T = any>(table: string, action: RealtimeAction, callback: RealtimeCallback<T>) {
|
|
261
|
-
return this.realtime.subscribe<T>(table, action, callback);
|
|
256
|
+
subscribe<T = any>(table: string, action: RealtimeAction, callback: RealtimeCallback<T>) {
|
|
257
|
+
return this.realtime.subscribe<T>(table, action, callback);
|
|
262
258
|
}
|
|
259
|
+
|
|
260
|
+
// Environment shortcuts
|
|
261
|
+
async getEnvironmentStatus() { return this.environments.status(); }
|
|
262
|
+
async initTestEnvironment() { return this.environments.init(); }
|
|
263
|
+
async promoteTestToProd() { return this.environments.promote(); }
|
|
264
|
+
async revertTestEnvironment() { return this.environments.revert(); }
|
|
263
265
|
}
|
package/src/http-client.ts
CHANGED
|
@@ -7,20 +7,17 @@ import type { RequestOptions } from './types';
|
|
|
7
7
|
|
|
8
8
|
export class HttpClient {
|
|
9
9
|
public url: string;
|
|
10
|
-
public
|
|
10
|
+
public apiKey: string = '';
|
|
11
11
|
public token: string | null = null;
|
|
12
|
+
private environment: string = 'prod';
|
|
12
13
|
|
|
13
|
-
constructor(url?: string,
|
|
14
|
+
constructor(url?: string, apiKey?: string) {
|
|
14
15
|
let baseUrl = url || (typeof window !== 'undefined' ? window.location.origin : 'http://localhost:8080');
|
|
15
16
|
this.url = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
16
|
-
|
|
17
|
-
if (
|
|
18
|
-
|
|
17
|
+
|
|
18
|
+
if (apiKey) this.apiKey = apiKey;
|
|
19
|
+
|
|
19
20
|
this.token = this.cleanValue(localStorage.getItem('baas_token'));
|
|
20
|
-
const storedProject = this.cleanValue(localStorage.getItem('baas_project_id'));
|
|
21
|
-
if (storedProject && !this.projectID) {
|
|
22
|
-
this.projectID = storedProject;
|
|
23
|
-
}
|
|
24
21
|
}
|
|
25
22
|
|
|
26
23
|
protected cleanValue(val: string | null): string | null {
|
|
@@ -32,13 +29,12 @@ export class HttpClient {
|
|
|
32
29
|
* Public header generator for adapters
|
|
33
30
|
*/
|
|
34
31
|
public getHeaders(contentType: string = 'application/json') {
|
|
35
|
-
const dynamicProject = this.getDynamicProjectID();
|
|
36
32
|
const dynamicToken = this.getDynamicToken();
|
|
37
|
-
|
|
33
|
+
|
|
38
34
|
const headers: Record<string, string> = {
|
|
39
|
-
'
|
|
35
|
+
'apikey': this.apiKey,
|
|
40
36
|
};
|
|
41
|
-
|
|
37
|
+
|
|
42
38
|
if (contentType) {
|
|
43
39
|
headers['Content-Type'] = contentType;
|
|
44
40
|
}
|
|
@@ -46,6 +42,11 @@ export class HttpClient {
|
|
|
46
42
|
if (dynamicToken) {
|
|
47
43
|
headers['Authorization'] = `Bearer ${dynamicToken}`;
|
|
48
44
|
}
|
|
45
|
+
|
|
46
|
+
if (this.environment && this.environment !== 'prod') {
|
|
47
|
+
headers['X-Environment'] = this.environment;
|
|
48
|
+
}
|
|
49
|
+
|
|
49
50
|
return headers;
|
|
50
51
|
}
|
|
51
52
|
|
|
@@ -53,39 +54,31 @@ export class HttpClient {
|
|
|
53
54
|
return this.cleanValue(this.token || localStorage.getItem('baas_token'));
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
public getDynamicProjectID() {
|
|
57
|
-
const stored = this.cleanValue(localStorage.getItem('baas_project_id'));
|
|
58
|
-
if (this.projectID && this.projectID !== 'default' && this.projectID !== '') {
|
|
59
|
-
return this.projectID;
|
|
60
|
-
}
|
|
61
|
-
return stored || 'default';
|
|
62
|
-
}
|
|
63
|
-
|
|
64
57
|
/**
|
|
65
58
|
* Core HTTP request method - DRY principle
|
|
66
59
|
*/
|
|
67
60
|
protected async request<T = any>(endpoint: string, options: RequestOptions = {}): Promise<T> {
|
|
68
61
|
const { method = 'GET', body, headers: customHeaders, skipAuth = false } = options;
|
|
69
|
-
|
|
62
|
+
|
|
70
63
|
const headers = { ...this.getHeaders(), ...customHeaders };
|
|
71
|
-
|
|
64
|
+
|
|
72
65
|
const fetchOptions: RequestInit = {
|
|
73
66
|
method,
|
|
74
67
|
headers,
|
|
75
68
|
};
|
|
76
|
-
|
|
69
|
+
|
|
77
70
|
if (body !== undefined) {
|
|
78
71
|
fetchOptions.body = JSON.stringify(body);
|
|
79
72
|
}
|
|
80
|
-
|
|
73
|
+
|
|
81
74
|
const res = await fetch(`${this.url}${endpoint}`, fetchOptions);
|
|
82
|
-
|
|
75
|
+
|
|
83
76
|
if (res.status === 204) {
|
|
84
77
|
return { success: true } as T;
|
|
85
78
|
}
|
|
86
|
-
|
|
79
|
+
|
|
87
80
|
const data = await res.json().catch(() => null);
|
|
88
|
-
|
|
81
|
+
|
|
89
82
|
if (!res.ok) {
|
|
90
83
|
if (res.status === 401 && !skipAuth) {
|
|
91
84
|
this.forceLogout();
|
|
@@ -95,7 +88,7 @@ export class HttpClient {
|
|
|
95
88
|
}
|
|
96
89
|
return { error: data?.error || `Request failed: ${res.status}`, ...data } as T;
|
|
97
90
|
}
|
|
98
|
-
|
|
91
|
+
|
|
99
92
|
return data;
|
|
100
93
|
}
|
|
101
94
|
|
|
@@ -119,6 +112,14 @@ export class HttpClient {
|
|
|
119
112
|
return this.request<T>(endpoint, { method: 'DELETE' });
|
|
120
113
|
}
|
|
121
114
|
|
|
115
|
+
setEnvironment(env: string) {
|
|
116
|
+
this.environment = env;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
getEnvironment(): string {
|
|
120
|
+
return this.environment;
|
|
121
|
+
}
|
|
122
|
+
|
|
122
123
|
logout() {
|
|
123
124
|
this.token = null;
|
|
124
125
|
localStorage.removeItem('baas_token');
|
package/src/index.ts
CHANGED
|
@@ -23,7 +23,6 @@ export type { QueryFilter, HttpMethod, RequestOptions, PaginationOptions, ApiRes
|
|
|
23
23
|
// Module types (for advanced usage)
|
|
24
24
|
export type { AuthModule } from './modules/auth';
|
|
25
25
|
export type { UsersModule } from './modules/users';
|
|
26
|
-
export type { ProjectsModule } from './modules/projects';
|
|
27
26
|
export type { DatabaseModule } from './modules/database';
|
|
28
27
|
export type { StorageModule } from './modules/storage';
|
|
29
28
|
export type { BackupsModule } from './modules/backups';
|
package/src/modules/backups.ts
CHANGED
|
@@ -43,8 +43,7 @@ export function createBackupsModule(client: HttpClient): BackupsModule {
|
|
|
43
43
|
|
|
44
44
|
getDownloadUrl(backupId: string) {
|
|
45
45
|
const token = client.getDynamicToken();
|
|
46
|
-
|
|
47
|
-
return `${client.url}/api/backups/${backupId}/download?access_token=${token}&project_id=${projectId}`;
|
|
46
|
+
return `${client.url}/api/backups/${backupId}/download?access_token=${token}&apikey=${client.apiKey}`;
|
|
48
47
|
},
|
|
49
48
|
|
|
50
49
|
async listTables() {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environments Module - Test/Prod environment management
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { HttpClient } from '../http-client';
|
|
6
|
+
|
|
7
|
+
export interface EnvironmentStatus {
|
|
8
|
+
test_exists: boolean;
|
|
9
|
+
test_status?: string;
|
|
10
|
+
test_created_at?: string;
|
|
11
|
+
test_schema_name?: string;
|
|
12
|
+
prod_schema_name: string;
|
|
13
|
+
table_count: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface PromoteResult {
|
|
17
|
+
tables_promoted: number;
|
|
18
|
+
status: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface EnvironmentsModule {
|
|
22
|
+
status(): Promise<EnvironmentStatus>;
|
|
23
|
+
init(): Promise<any>;
|
|
24
|
+
promote(): Promise<PromoteResult>;
|
|
25
|
+
revert(): Promise<any>;
|
|
26
|
+
setActive(env: 'test' | 'prod'): void;
|
|
27
|
+
getActive(): string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function createEnvironmentsModule(client: HttpClient): EnvironmentsModule {
|
|
31
|
+
const get = (endpoint: string) => (client as any).get(endpoint);
|
|
32
|
+
const post = (endpoint: string, body?: unknown) => (client as any).post(endpoint, body);
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
async status() {
|
|
36
|
+
return get('/api/environments/status');
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
async init() {
|
|
40
|
+
return post('/api/environments/init');
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
async promote() {
|
|
44
|
+
return post('/api/environments/promote');
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
async revert() {
|
|
48
|
+
return post('/api/environments/revert');
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
setActive(env: 'test' | 'prod') {
|
|
52
|
+
client.setEnvironment(env);
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
getActive() {
|
|
56
|
+
return client.getEnvironment();
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
package/src/modules/realtime.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface RealtimeModule {
|
|
|
17
17
|
export function createRealtimeModule(client: HttpClient): RealtimeModule {
|
|
18
18
|
const service = new RealtimeService(
|
|
19
19
|
client.url,
|
|
20
|
-
client.
|
|
20
|
+
client.apiKey,
|
|
21
21
|
() => client.getDynamicToken(),
|
|
22
22
|
typeof WebSocket !== 'undefined' ? WebSocket : undefined
|
|
23
23
|
);
|
package/src/realtime.ts
CHANGED
|
@@ -13,7 +13,7 @@ export class RealtimeService {
|
|
|
13
13
|
|
|
14
14
|
constructor(
|
|
15
15
|
private url: string,
|
|
16
|
-
private
|
|
16
|
+
private apiKey: string,
|
|
17
17
|
private tokenProvider: () => string | null,
|
|
18
18
|
private wsConstructor: any = typeof WebSocket !== 'undefined' ? WebSocket : null
|
|
19
19
|
) {}
|
|
@@ -26,14 +26,14 @@ export class RealtimeService {
|
|
|
26
26
|
|
|
27
27
|
return new Promise((resolve, reject) => {
|
|
28
28
|
const token = this.tokenProvider();
|
|
29
|
-
if (!this.
|
|
30
|
-
reject(new Error('Missing
|
|
29
|
+
if (!this.apiKey || !token) {
|
|
30
|
+
reject(new Error('Missing API key or authentication token for Realtime connection'));
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// Convert http/https to ws/wss
|
|
35
35
|
const wsUrl = this.url.replace(/^http/, 'ws') + '/ws';
|
|
36
|
-
const fullUrl = `${wsUrl}?
|
|
36
|
+
const fullUrl = `${wsUrl}?apikey=${this.apiKey}&token=${token}`;
|
|
37
37
|
|
|
38
38
|
if (!this.wsConstructor) {
|
|
39
39
|
reject(new Error('WebSocket constructor not provided or available in this environment'));
|
package/src/modules/projects.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Projects Module - Project management operations
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { HttpClient } from '../http-client';
|
|
6
|
-
|
|
7
|
-
export interface ProjectsModule {
|
|
8
|
-
list(): Promise<any>;
|
|
9
|
-
create(name: string): Promise<any>;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function createProjectsModule(client: HttpClient): ProjectsModule {
|
|
13
|
-
const get = (endpoint: string) => (client as any).get(endpoint);
|
|
14
|
-
const post = (endpoint: string, body?: unknown) => (client as any).post(endpoint, body);
|
|
15
|
-
|
|
16
|
-
return {
|
|
17
|
-
async list() {
|
|
18
|
-
return get('/api/projects');
|
|
19
|
-
},
|
|
20
|
-
|
|
21
|
-
async create(name: string) {
|
|
22
|
-
return post('/api/projects', { name });
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
}
|