@mitralab.io/platform-sdk 1.0.1

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.js ADDED
@@ -0,0 +1,763 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ MitraApiError: () => MitraApiError,
24
+ createClient: () => createClient
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/utils/http-client.ts
29
+ var HttpClient = class {
30
+ baseUrl;
31
+ tokenGetter;
32
+ onUnauthorized;
33
+ onError;
34
+ defaultHeaders;
35
+ constructor(config) {
36
+ this.baseUrl = config.baseUrl.replace(/\/$/, "");
37
+ this.tokenGetter = config.getToken ?? (() => null);
38
+ this.onUnauthorized = config.onUnauthorized;
39
+ this.onError = config.onError;
40
+ this.defaultHeaders = config.defaultHeaders ?? {};
41
+ }
42
+ /**
43
+ * Returns the current authentication token.
44
+ * @returns The JWT token if authenticated, null otherwise
45
+ */
46
+ getToken() {
47
+ return this.tokenGetter();
48
+ }
49
+ /**
50
+ * Makes an HTTP request with automatic JSON handling and authentication.
51
+ *
52
+ * @param path - API endpoint path (e.g., '/users')
53
+ * @param options - Request options including method, body, headers, and params
54
+ * @returns Promise resolving to the parsed JSON response
55
+ * @throws {MitraApiError} When the API returns an error response
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * const result = await client.request<User>('/users/123', {
60
+ * method: 'PUT',
61
+ * body: { name: 'Updated Name' },
62
+ * });
63
+ * ```
64
+ */
65
+ async request(path, options = {}) {
66
+ const { method = "GET", body, headers = {}, params, isRetry } = options;
67
+ let url = `${this.baseUrl}${path}`;
68
+ if (params) {
69
+ const searchParams = new URLSearchParams();
70
+ Object.entries(params).forEach(([key, value]) => {
71
+ if (value !== void 0) {
72
+ searchParams.append(key, String(value));
73
+ }
74
+ });
75
+ const queryString = searchParams.toString();
76
+ if (queryString) {
77
+ url += `?${queryString}`;
78
+ }
79
+ }
80
+ const requestHeaders = {
81
+ "Content-Type": "application/json",
82
+ ...this.defaultHeaders,
83
+ ...headers
84
+ };
85
+ const token = this.tokenGetter();
86
+ if (token) {
87
+ requestHeaders["Authorization"] = `Bearer ${token}`;
88
+ }
89
+ const response = await fetch(url, {
90
+ method,
91
+ headers: requestHeaders,
92
+ body: body ? JSON.stringify(body) : void 0
93
+ });
94
+ if (!response.ok) {
95
+ if (response.status === 401 && !isRetry && this.onUnauthorized) {
96
+ const refreshed = await this.onUnauthorized();
97
+ if (refreshed) {
98
+ return this.request(path, { ...options, isRetry: true });
99
+ }
100
+ }
101
+ const errorBody = await response.json().catch(() => ({}));
102
+ const error = new MitraApiError(
103
+ errorBody.message || `Request failed with status ${response.status}`,
104
+ response.status,
105
+ errorBody.error_code,
106
+ errorBody
107
+ );
108
+ this.onError?.(error);
109
+ throw error;
110
+ }
111
+ if (response.status === 204) {
112
+ return void 0;
113
+ }
114
+ return response.json();
115
+ }
116
+ /**
117
+ * Makes a GET request.
118
+ *
119
+ * @param path - API endpoint path
120
+ * @param params - Optional query parameters
121
+ * @returns Promise resolving to the parsed JSON response
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * const users = await client.get<User[]>('/users', { limit: 10 });
126
+ * ```
127
+ */
128
+ get(path, params) {
129
+ return this.request(path, { method: "GET", params });
130
+ }
131
+ /**
132
+ * Makes a POST request.
133
+ *
134
+ * @param path - API endpoint path
135
+ * @param body - Request body (will be JSON stringified)
136
+ * @returns Promise resolving to the parsed JSON response
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * const user = await client.post<User>('/users', { name: 'John', email: 'john@example.com' });
141
+ * ```
142
+ */
143
+ post(path, body) {
144
+ return this.request(path, { method: "POST", body });
145
+ }
146
+ /**
147
+ * Makes a PUT request.
148
+ *
149
+ * @param path - API endpoint path
150
+ * @param body - Request body (will be JSON stringified)
151
+ * @returns Promise resolving to the parsed JSON response
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * const user = await client.put<User>('/users/123', { name: 'Updated Name' });
156
+ * ```
157
+ */
158
+ put(path, body) {
159
+ return this.request(path, { method: "PUT", body });
160
+ }
161
+ /**
162
+ * Makes a DELETE request.
163
+ *
164
+ * @param path - API endpoint path
165
+ * @param params - Optional query parameters
166
+ * @returns Promise resolving to the parsed JSON response (or undefined for 204 responses)
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * await client.delete('/users/123');
171
+ * ```
172
+ */
173
+ delete(path, params) {
174
+ return this.request(path, { method: "DELETE", params });
175
+ }
176
+ };
177
+ var MitraApiError = class extends Error {
178
+ constructor(message, status, code, details) {
179
+ super(message);
180
+ this.status = status;
181
+ this.code = code;
182
+ this.details = details;
183
+ this.name = "MitraApiError";
184
+ }
185
+ };
186
+
187
+ // src/modules/auth.ts
188
+ var AuthModule = class {
189
+ appId;
190
+ _currentUser = null;
191
+ _accessToken = null;
192
+ _refreshToken = null;
193
+ refreshPromise = null;
194
+ listeners = /* @__PURE__ */ new Set();
195
+ storageKey;
196
+ publicClient;
197
+ authedClient;
198
+ constructor(appId, iamBaseUrl) {
199
+ this.appId = appId;
200
+ this.storageKey = `mitra_auth_${appId}`;
201
+ this.publicClient = new HttpClient({ baseUrl: iamBaseUrl, getToken: () => null });
202
+ this.authedClient = new HttpClient({ baseUrl: iamBaseUrl, getToken: () => this._accessToken });
203
+ this.loadFromStorage();
204
+ }
205
+ /** The currently authenticated user, or null. */
206
+ get currentUser() {
207
+ return this._currentUser;
208
+ }
209
+ /** The current JWT access token, or null. */
210
+ get accessToken() {
211
+ return this._accessToken;
212
+ }
213
+ /** Whether a user is currently authenticated (local check, not server-validated). */
214
+ get isAuthenticated() {
215
+ return this._currentUser !== null && this._accessToken !== null;
216
+ }
217
+ /**
218
+ * Signs in a user with email and password.
219
+ *
220
+ * On success, stores access token, refresh token, and user data.
221
+ * Subsequent API requests use the token automatically.
222
+ *
223
+ * @param credentials - Email and password.
224
+ * @returns The authenticated user.
225
+ * @throws {MitraApiError} On invalid credentials (401).
226
+ *
227
+ * @example
228
+ * ```typescript
229
+ * const user = await mitra.auth.signIn({
230
+ * email: 'user@example.com',
231
+ * password: 'password123',
232
+ * });
233
+ * ```
234
+ */
235
+ async signIn(credentials) {
236
+ const tokenResponse = await this.publicClient.post(
237
+ "/api/v1/auth/tokens",
238
+ credentials
239
+ );
240
+ this._accessToken = tokenResponse.accessToken;
241
+ this._refreshToken = tokenResponse.refreshToken;
242
+ const user = await this.authedClient.get("/api/v1/auth/me");
243
+ this.setAuthState(user, tokenResponse.accessToken, tokenResponse.refreshToken);
244
+ return user;
245
+ }
246
+ /**
247
+ * Registers a new user and signs them in automatically.
248
+ *
249
+ * @param data - Email, password, and optional name.
250
+ * @returns The newly created and authenticated user.
251
+ * @throws {MitraApiError} On duplicate email (409) or validation error (400).
252
+ *
253
+ * @example
254
+ * ```typescript
255
+ * const user = await mitra.auth.signUp({
256
+ * email: 'new@example.com',
257
+ * password: 'securepassword',
258
+ * name: 'Jane Doe',
259
+ * });
260
+ * ```
261
+ */
262
+ async signUp(data) {
263
+ await this.publicClient.post("/api/v1/auth/users/register", {
264
+ ...data,
265
+ appId: this.appId
266
+ });
267
+ return this.signIn({ email: data.email, password: data.password });
268
+ }
269
+ /**
270
+ * Signs out the current user, clearing all auth state and localStorage.
271
+ *
272
+ * @param redirectUrl - Optional URL to navigate to after sign-out.
273
+ *
274
+ * @example
275
+ * ```typescript
276
+ * mitra.auth.signOut();
277
+ * mitra.auth.signOut('/login');
278
+ * ```
279
+ */
280
+ signOut(redirectUrl) {
281
+ this.clearAuthState();
282
+ if (globalThis.window !== void 0 && redirectUrl) {
283
+ globalThis.window.location.href = redirectUrl;
284
+ }
285
+ }
286
+ /**
287
+ * Refreshes the session using the stored refresh token.
288
+ *
289
+ * Called automatically by the SDK on 401 responses. Can also be called
290
+ * manually. Multiple concurrent calls are deduplicated (only one refresh
291
+ * request is made).
292
+ *
293
+ * @returns `true` if refresh succeeded, `false` otherwise.
294
+ *
295
+ * @example
296
+ * ```typescript
297
+ * const ok = await mitra.auth.refreshSession();
298
+ * if (!ok) mitra.auth.redirectToLogin();
299
+ * ```
300
+ */
301
+ async refreshSession() {
302
+ if (!this._refreshToken) return false;
303
+ if (this.refreshPromise) return this.refreshPromise;
304
+ this.refreshPromise = this.doRefresh();
305
+ try {
306
+ return await this.refreshPromise;
307
+ } finally {
308
+ this.refreshPromise = null;
309
+ }
310
+ }
311
+ /**
312
+ * Fetches the current user from the server and updates local state.
313
+ *
314
+ * Only clears auth state on 401 (expired/invalid token).
315
+ * Transient errors (500, network) return null without clearing the session.
316
+ *
317
+ * @returns The user if authenticated, `null` otherwise.
318
+ *
319
+ * @example
320
+ * ```typescript
321
+ * const user = await mitra.auth.me();
322
+ * if (!user) console.log('Not authenticated');
323
+ * ```
324
+ */
325
+ async me() {
326
+ if (!this._accessToken) return null;
327
+ try {
328
+ const user = await this.authedClient.get("/api/v1/auth/me");
329
+ this._currentUser = user;
330
+ this.saveToStorage();
331
+ this.notifyListeners();
332
+ return user;
333
+ } catch (error) {
334
+ if (error instanceof MitraApiError && error.status === 401) {
335
+ this.clearAuthState();
336
+ }
337
+ return null;
338
+ }
339
+ }
340
+ /**
341
+ * Validates the current session with the server.
342
+ *
343
+ * @returns `true` if the session is valid, `false` otherwise.
344
+ *
345
+ * @example
346
+ * ```typescript
347
+ * const valid = await mitra.auth.checkAuth();
348
+ * if (!valid) mitra.auth.redirectToLogin();
349
+ * ```
350
+ */
351
+ async checkAuth() {
352
+ return await this.me() !== null;
353
+ }
354
+ /**
355
+ * Sets the access token manually (e.g., from SSO/OAuth callback).
356
+ *
357
+ * Call `me()` afterwards to fetch the associated user data.
358
+ *
359
+ * @param token - JWT access token.
360
+ * @param saveToStorage - Whether to persist to localStorage (default: true).
361
+ *
362
+ * @example
363
+ * ```typescript
364
+ * mitra.auth.setToken(tokenFromCallback);
365
+ * await mitra.auth.me();
366
+ * ```
367
+ */
368
+ setToken(token, saveToStorage = true) {
369
+ this._accessToken = token;
370
+ if (saveToStorage) {
371
+ this.saveToStorage();
372
+ }
373
+ }
374
+ /**
375
+ * Redirects to `/login?returnUrl=...` for unauthenticated users.
376
+ *
377
+ * @param returnUrl - URL to return to after login (default: '/').
378
+ *
379
+ * @example
380
+ * ```typescript
381
+ * if (!mitra.auth.isAuthenticated) {
382
+ * mitra.auth.redirectToLogin(window.location.pathname);
383
+ * }
384
+ * ```
385
+ */
386
+ redirectToLogin(returnUrl = "/") {
387
+ if (globalThis.window === void 0) return;
388
+ globalThis.window.location.href = `/login?returnUrl=${encodeURIComponent(returnUrl)}`;
389
+ }
390
+ /**
391
+ * Registers a callback for auth state changes.
392
+ *
393
+ * Called immediately with the current state, then on every sign-in/sign-out.
394
+ *
395
+ * @param callback - Receives the User on login, null on logout.
396
+ * @returns Unsubscribe function.
397
+ *
398
+ * @example
399
+ * ```typescript
400
+ * useEffect(() => {
401
+ * const unsub = mitra.auth.onAuthStateChange((user) => {
402
+ * setUser(user);
403
+ * setLoading(false);
404
+ * });
405
+ * return unsub;
406
+ * }, []);
407
+ * ```
408
+ */
409
+ onAuthStateChange(callback) {
410
+ this.listeners.add(callback);
411
+ callback(this._currentUser);
412
+ return () => {
413
+ this.listeners.delete(callback);
414
+ };
415
+ }
416
+ async doRefresh() {
417
+ try {
418
+ const tokenResponse = await this.publicClient.post(
419
+ "/api/v1/auth/tokens/refresh",
420
+ { refreshToken: this._refreshToken }
421
+ );
422
+ this._accessToken = tokenResponse.accessToken;
423
+ this._refreshToken = tokenResponse.refreshToken;
424
+ const user = await this.authedClient.get("/api/v1/auth/me");
425
+ this.setAuthState(user, tokenResponse.accessToken, tokenResponse.refreshToken);
426
+ return true;
427
+ } catch {
428
+ this.clearAuthState();
429
+ return false;
430
+ }
431
+ }
432
+ setAuthState(user, token, refreshToken) {
433
+ this._currentUser = user;
434
+ this._accessToken = token;
435
+ this._refreshToken = refreshToken;
436
+ this.saveToStorage();
437
+ this.notifyListeners();
438
+ }
439
+ clearAuthState() {
440
+ this._currentUser = null;
441
+ this._accessToken = null;
442
+ this._refreshToken = null;
443
+ this.removeFromStorage();
444
+ this.notifyListeners();
445
+ }
446
+ notifyListeners() {
447
+ this.listeners.forEach((callback) => {
448
+ try {
449
+ callback(this._currentUser);
450
+ } catch (error) {
451
+ console.error("Auth state change listener error:", error);
452
+ }
453
+ });
454
+ }
455
+ saveToStorage() {
456
+ if (typeof localStorage === "undefined") return;
457
+ try {
458
+ localStorage.setItem(
459
+ this.storageKey,
460
+ JSON.stringify({
461
+ user: this._currentUser,
462
+ token: this._accessToken,
463
+ refreshToken: this._refreshToken
464
+ })
465
+ );
466
+ } catch {
467
+ }
468
+ }
469
+ loadFromStorage() {
470
+ if (typeof localStorage === "undefined") return;
471
+ try {
472
+ const stored = localStorage.getItem(this.storageKey);
473
+ if (stored) {
474
+ const { user, token, refreshToken } = JSON.parse(stored);
475
+ this._currentUser = user;
476
+ this._accessToken = token;
477
+ this._refreshToken = refreshToken ?? null;
478
+ }
479
+ } catch {
480
+ this.removeFromStorage();
481
+ }
482
+ }
483
+ removeFromStorage() {
484
+ if (typeof localStorage === "undefined") return;
485
+ try {
486
+ localStorage.removeItem(this.storageKey);
487
+ } catch {
488
+ }
489
+ }
490
+ };
491
+
492
+ // src/modules/entities.ts
493
+ var EntitiesModule = class _EntitiesModule {
494
+ httpClient;
495
+ dataSourceId;
496
+ tableProxies = /* @__PURE__ */ new Map();
497
+ constructor(httpClient, dataSourceId) {
498
+ this.httpClient = httpClient;
499
+ this.dataSourceId = dataSourceId;
500
+ }
501
+ static createProxy(httpClient, dataSourceId) {
502
+ const instance = new _EntitiesModule(httpClient, dataSourceId);
503
+ return new Proxy(instance, {
504
+ get: (target, prop) => {
505
+ if (prop in target) {
506
+ return target[prop];
507
+ }
508
+ return target.getTable(prop);
509
+ }
510
+ });
511
+ }
512
+ setDataSourceId(dataSourceId) {
513
+ this.dataSourceId = dataSourceId;
514
+ this.tableProxies.clear();
515
+ }
516
+ getTable(tableName) {
517
+ if (!this.tableProxies.has(tableName)) {
518
+ this.tableProxies.set(tableName, this.createTableAccessor(tableName));
519
+ }
520
+ return this.tableProxies.get(tableName);
521
+ }
522
+ createTableAccessor(tableName) {
523
+ const basePath = `/api/v1/data-sources/${this.dataSourceId}/tables/${tableName}/records`;
524
+ return {
525
+ list: async (sortOrOptions, limit, skip, fields) => {
526
+ let params;
527
+ if (typeof sortOrOptions === "string" || sortOrOptions === void 0) {
528
+ params = {
529
+ sort: sortOrOptions,
530
+ limit,
531
+ skip,
532
+ fields: fields?.join(",")
533
+ };
534
+ } else {
535
+ params = {
536
+ sort: sortOrOptions.sort,
537
+ limit: sortOrOptions.limit,
538
+ skip: sortOrOptions.skip,
539
+ fields: sortOrOptions.fields?.join(",")
540
+ };
541
+ }
542
+ const response = await this.httpClient.get(basePath, params);
543
+ return response.data;
544
+ },
545
+ filter: async (query, sort, limit, skip, fields) => {
546
+ const params = {
547
+ q: JSON.stringify(query),
548
+ sort,
549
+ limit,
550
+ skip,
551
+ fields: fields?.join(",")
552
+ };
553
+ const response = await this.httpClient.get(basePath, params);
554
+ return response.data;
555
+ },
556
+ get: async (id) => {
557
+ return this.httpClient.get(`${basePath}/${id}`);
558
+ },
559
+ create: async (data) => {
560
+ return this.httpClient.post(basePath, data);
561
+ },
562
+ update: async (id, data) => {
563
+ return this.httpClient.put(`${basePath}/${id}`, data);
564
+ },
565
+ delete: async (id) => {
566
+ return this.httpClient.delete(`${basePath}/${id}`);
567
+ },
568
+ deleteMany: async (query) => {
569
+ return this.httpClient.delete(basePath, {
570
+ q: JSON.stringify(query)
571
+ });
572
+ },
573
+ bulkCreate: async (data) => {
574
+ return this.httpClient.post(`${basePath}/bulk`, data);
575
+ }
576
+ };
577
+ }
578
+ };
579
+
580
+ // src/modules/functions.ts
581
+ var FunctionsModule = class {
582
+ httpClient;
583
+ constructor(httpClient) {
584
+ this.httpClient = httpClient;
585
+ }
586
+ /**
587
+ * Executes a serverless function by ID.
588
+ *
589
+ * Triggers the function's current published version with the provided input.
590
+ *
591
+ * @param functionId - UUID of the function to execute.
592
+ * @param input - Input data to pass to the function.
593
+ * @returns The execution result with status, output, and metadata.
594
+ * @throws {MitraApiError} On function not found (404) or unauthorized (401).
595
+ *
596
+ * @example
597
+ * ```typescript
598
+ * const execution = await mitra.functions.execute('fn-id', { key: 'value' });
599
+ * console.log(execution.status, execution.output);
600
+ * ```
601
+ */
602
+ async execute(functionId, input) {
603
+ return this.httpClient.post(
604
+ `/api/v1/functions/${functionId}/execute`,
605
+ input ? { input } : void 0
606
+ );
607
+ }
608
+ };
609
+
610
+ // src/modules/integration.ts
611
+ var IntegrationModule = class {
612
+ httpClient;
613
+ constructor(httpClient) {
614
+ this.httpClient = httpClient;
615
+ }
616
+ /**
617
+ * Executes a pre-defined integration resource by ID.
618
+ *
619
+ * The resource's endpoint, method, and body are resolved server-side
620
+ * using the provided parameters. Only declared parameters can be passed.
621
+ *
622
+ * @param resourceId - UUID of the integration resource.
623
+ * @param params - Named parameters declared in the resource's params schema.
624
+ * @returns Proxy result with status, headers, body, and execution metadata.
625
+ * @throws {MitraApiError} On resource not found (404) or external API failure.
626
+ *
627
+ * @example
628
+ * ```typescript
629
+ * const result = await mitra.integration.executeResource('resource-id', {
630
+ * descricao: 'Notebook',
631
+ * limit: 10,
632
+ * });
633
+ * console.log(result.body);
634
+ * ```
635
+ */
636
+ async executeResource(resourceId, params) {
637
+ return this.httpClient.post(
638
+ `/api/v1/proxy/resources/${resourceId}/execute`,
639
+ { params }
640
+ );
641
+ }
642
+ /**
643
+ * Executes a proxied HTTP request through an integration config.
644
+ *
645
+ * The Mitra server handles authentication and injects credentials automatically.
646
+ * Note: integrations configured with RESOURCE_ONLY mode will block direct proxy access.
647
+ *
648
+ * @param configId - UUID of the integration config.
649
+ * @param request - The HTTP request to proxy (method, endpoint, body, etc.).
650
+ * @returns Proxy result with status, headers, body, and execution metadata.
651
+ * @throws {MitraApiError} On config not found (404) or external API failure.
652
+ */
653
+ async execute(configId, request) {
654
+ return this.httpClient.post(
655
+ `/api/v1/proxy/template-configs/${configId}/execute`,
656
+ { ...request, source: "SDK" }
657
+ );
658
+ }
659
+ };
660
+
661
+ // src/modules/queries.ts
662
+ var QueriesModule = class {
663
+ httpClient;
664
+ dataSourceId = "";
665
+ constructor(httpClient) {
666
+ this.httpClient = httpClient;
667
+ }
668
+ /** @internal Called by client.init() to set the resolved data source. */
669
+ setDataSourceId(dataSourceId) {
670
+ this.dataSourceId = dataSourceId;
671
+ }
672
+ /**
673
+ * Executes a named query.
674
+ *
675
+ * @param id - UUID of the custom query.
676
+ * @param parameters - Named parameters for the prepared statement.
677
+ * @returns Query result with rows and affected row count.
678
+ * @throws {MitraApiError} On query not found (404).
679
+ *
680
+ * @example
681
+ * ```typescript
682
+ * const result = await mitra.queries.execute('query-id', { status: 'active' });
683
+ * console.log(`Found ${result.rows.length} rows`);
684
+ * ```
685
+ */
686
+ async execute(id, parameters) {
687
+ return this.httpClient.post(
688
+ `/api/v1/custom-queries/${id}/execute`,
689
+ { datasourceId: this.dataSourceId, parameters }
690
+ );
691
+ }
692
+ };
693
+
694
+ // src/client.ts
695
+ function createClient(config) {
696
+ const { appId, apiUrl, onError } = config;
697
+ const iamUrl = `${apiUrl}/iam`;
698
+ const dataManagerUrl = `${apiUrl}/data-manager`;
699
+ const functionsUrl = `${apiUrl}/functions`;
700
+ const integrationUrl = `${apiUrl}/integration`;
701
+ const codeStudioUrl = `${apiUrl}/code-studio`;
702
+ const authModule = new AuthModule(appId, iamUrl);
703
+ const onUnauthorized = () => authModule.refreshSession();
704
+ const defaultHeaders = { "X-App-Id": appId };
705
+ const httpClient = new HttpClient({
706
+ baseUrl: dataManagerUrl,
707
+ getToken: () => authModule.accessToken,
708
+ onUnauthorized,
709
+ onError,
710
+ defaultHeaders
711
+ });
712
+ const entitiesModule = EntitiesModule.createProxy(httpClient, "");
713
+ const functionsHttpClient = new HttpClient({
714
+ baseUrl: functionsUrl,
715
+ getToken: () => authModule.accessToken,
716
+ onUnauthorized,
717
+ onError,
718
+ defaultHeaders
719
+ });
720
+ const functionsModule = new FunctionsModule(functionsHttpClient);
721
+ const integrationHttpClient = new HttpClient({
722
+ baseUrl: integrationUrl,
723
+ getToken: () => authModule.accessToken,
724
+ onUnauthorized,
725
+ onError,
726
+ defaultHeaders
727
+ });
728
+ const integrationModule = new IntegrationModule(integrationHttpClient);
729
+ const queriesModule = new QueriesModule(httpClient);
730
+ let initialized = false;
731
+ let allowSignup = true;
732
+ async function init() {
733
+ if (initialized) return;
734
+ const publicClient = new HttpClient({
735
+ baseUrl: codeStudioUrl,
736
+ getToken: () => null
737
+ });
738
+ const appInfo = await publicClient.get(
739
+ `/api/v1/apps/${appId}/info`
740
+ );
741
+ entitiesModule.setDataSourceId(appInfo.dataSourceId);
742
+ queriesModule.setDataSourceId(appInfo.dataSourceId);
743
+ allowSignup = appInfo.allowSignup;
744
+ initialized = true;
745
+ }
746
+ return {
747
+ init,
748
+ auth: authModule,
749
+ entities: entitiesModule,
750
+ functions: functionsModule,
751
+ integration: integrationModule,
752
+ queries: queriesModule,
753
+ get allowSignup() {
754
+ return allowSignup;
755
+ },
756
+ config
757
+ };
758
+ }
759
+ // Annotate the CommonJS export names for ESM import in node:
760
+ 0 && (module.exports = {
761
+ MitraApiError,
762
+ createClient
763
+ });