@base44/sdk 0.1.0 → 0.1.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/dist/index.esm.js CHANGED
@@ -1,672 +1 @@
1
- import axios from 'axios';
2
-
3
- class Base44Error extends Error {
4
- constructor(message, status, code, data, originalError) {
5
- super(message);
6
- this.name = 'Base44Error';
7
- this.status = status;
8
- this.code = code;
9
- this.data = data;
10
- this.originalError = originalError;
11
- }
12
-
13
- // Add a method to safely serialize this error without circular references
14
- toJSON() {
15
- return {
16
- name: this.name,
17
- message: this.message,
18
- status: this.status,
19
- code: this.code,
20
- data: this.data
21
- };
22
- }
23
- }
24
-
25
- /**
26
- * Safely logs error information without circular references
27
- * @param {string} prefix - Prefix for the log message
28
- * @param {Error} error - The error to log
29
- */
30
- function safeErrorLog(prefix, error) {
31
- if (error instanceof Base44Error) {
32
- console.error(`${prefix} ${error.status}: ${error.message}`);
33
- if (error.data) {
34
- try {
35
- console.error('Error data:', JSON.stringify(error.data, null, 2));
36
- } catch (e) {
37
- console.error('Error data: [Cannot stringify error data]');
38
- }
39
- }
40
- } else {
41
- console.error(`${prefix} ${error.message}`);
42
- }
43
- }
44
-
45
- /**
46
- * Redirects to the login page with the current URL as return destination
47
- * @param {string} serverUrl - Base server URL
48
- * @param {string|number} appId - Application ID
49
- */
50
- function redirectToLogin(serverUrl, appId) {
51
- if (typeof window === 'undefined') {
52
- return; // Can't redirect in non-browser environment
53
- }
54
- const currentUrl = encodeURIComponent(window.location.href);
55
- const loginUrl = `${serverUrl}/login?from_url=${currentUrl}&app_id=${appId}`;
56
- window.location.href = loginUrl;
57
- }
58
-
59
- /**
60
- * Creates an axios client with default configuration and interceptors
61
- * @param {Object} options - Client configuration options
62
- * @param {string} options.baseURL - Base URL for all requests
63
- * @param {Object} options.headers - Additional headers
64
- * @param {string} options.token - Auth token
65
- * @param {boolean} options.requiresAuth - Whether the application requires authentication
66
- * @param {string|number} options.appId - Application ID (needed for login redirect)
67
- * @param {string} options.serverUrl - Server URL (needed for login redirect)
68
- * @returns {import('axios').AxiosInstance} Configured axios instance
69
- */
70
- function createAxiosClient(_ref) {
71
- let {
72
- baseURL,
73
- headers = {},
74
- token,
75
- requiresAuth = false,
76
- appId,
77
- serverUrl
78
- } = _ref;
79
- const client = axios.create({
80
- baseURL,
81
- headers: {
82
- 'Content-Type': 'application/json',
83
- 'Accept': 'application/json',
84
- ...headers
85
- }
86
- });
87
-
88
- // Add token to requests if available
89
- if (token) {
90
- client.defaults.headers.common['Authorization'] = `Bearer ${token}`;
91
- }
92
-
93
- // Add origin URL in browser environment
94
- client.interceptors.request.use(config => {
95
- if (typeof window !== 'undefined') {
96
- config.headers = {
97
- ...config.headers,
98
- 'X-Origin-URL': window.location.href
99
- };
100
- }
101
- return config;
102
- });
103
-
104
- // Handle responses
105
- client.interceptors.response.use(response => response.data, error => {
106
- const message = error.response?.data?.message || error.response?.data?.detail || error.message;
107
- const base44Error = new Base44Error(message, error.response?.status, error.response?.data?.code, error.response?.data, error);
108
-
109
- // Log errors in development
110
- if (process.env.NODE_ENV !== 'production') {
111
- safeErrorLog('[Base44 SDK Error]', base44Error);
112
- }
113
-
114
- // Check for 403 Forbidden (authentication required) and redirect to login if requiresAuth is true
115
- console.log(requiresAuth, error.response?.status, typeof window !== 'undefined');
116
- if (requiresAuth && error.response?.status === 403 && typeof window !== 'undefined') {
117
- console.log('Authentication required. Redirecting to login...');
118
- // Use a slight delay to allow the error to propagate first
119
- setTimeout(() => {
120
- redirectToLogin(serverUrl, appId);
121
- }, 100);
122
- }
123
- return Promise.reject(base44Error);
124
- });
125
- return client;
126
- }
127
-
128
- /**
129
- * Creates the entities module for the Base44 SDK
130
- * @param {import('axios').AxiosInstance} axios - Axios instance
131
- * @param {string|number} appId - Application ID
132
- * @returns {Object} Entities module
133
- */
134
- function createEntitiesModule(axios, appId) {
135
- // Using Proxy to dynamically handle entity names
136
- return new Proxy({}, {
137
- get(target, entityName) {
138
- // Don't create handlers for internal properties
139
- if (typeof entityName !== 'string' || entityName === 'then' || entityName.startsWith('_')) {
140
- return undefined;
141
- }
142
-
143
- // Create entity handler
144
- return createEntityHandler(axios, appId, entityName);
145
- }
146
- });
147
- }
148
-
149
- /**
150
- * Creates a handler for a specific entity
151
- * @param {import('axios').AxiosInstance} axios - Axios instance
152
- * @param {string|number} appId - Application ID
153
- * @param {string} entityName - Entity name
154
- * @returns {Object} Entity handler with CRUD methods
155
- */
156
- function createEntityHandler(axios, appId, entityName) {
157
- const baseURL = `/apps/${appId}/entities/${entityName}`;
158
- return {
159
- /**
160
- * List entities with optional pagination and sorting
161
- * @param {string} [sort] - Sort parameter
162
- * @param {number} [limit] - Limit results
163
- * @param {number} [skip] - Skip results (pagination)
164
- * @param {string[]} [fields] - Fields to include
165
- * @returns {Promise<Array>} List of entities
166
- */
167
- async list(sort, limit, skip, fields) {
168
- const params = {};
169
- if (sort) params.sort = sort;
170
- if (limit) params.limit = limit;
171
- if (skip) params.skip = skip;
172
- if (fields) params.fields = Array.isArray(fields) ? fields.join(',') : fields;
173
- return axios.get(baseURL, {
174
- params
175
- });
176
- },
177
- /**
178
- * Filter entities based on query
179
- * @param {Object} query - Filter query
180
- * @param {string} [sort] - Sort parameter
181
- * @param {number} [limit] - Limit results
182
- * @param {number} [skip] - Skip results (pagination)
183
- * @param {string[]} [fields] - Fields to include
184
- * @returns {Promise<Array>} Filtered entities
185
- */
186
- async filter(query, sort, limit, skip, fields) {
187
- const params = {
188
- q: JSON.stringify(query)
189
- };
190
- if (sort) params.sort = sort;
191
- if (limit) params.limit = limit;
192
- if (skip) params.skip = skip;
193
- if (fields) params.fields = Array.isArray(fields) ? fields.join(',') : fields;
194
- return axios.get(baseURL, {
195
- params
196
- });
197
- },
198
- /**
199
- * Get entity by ID
200
- * @param {string} id - Entity ID
201
- * @returns {Promise<Object>} Entity
202
- */
203
- async get(id) {
204
- return axios.get(`${baseURL}/${id}`);
205
- },
206
- /**
207
- * Create new entity
208
- * @param {Object} data - Entity data
209
- * @returns {Promise<Object>} Created entity
210
- */
211
- async create(data) {
212
- return axios.post(baseURL, data);
213
- },
214
- /**
215
- * Update entity by ID
216
- * @param {string} id - Entity ID
217
- * @param {Object} data - Updated entity data
218
- * @returns {Promise<Object>} Updated entity
219
- */
220
- async update(id, data) {
221
- return axios.put(`${baseURL}/${id}`, data);
222
- },
223
- /**
224
- * Delete entity by ID
225
- * @param {string} id - Entity ID
226
- * @returns {Promise<void>}
227
- */
228
- async delete(id) {
229
- return axios.delete(`${baseURL}/${id}`);
230
- },
231
- /**
232
- * Delete multiple entities based on query
233
- * @param {Object} query - Delete query
234
- * @returns {Promise<void>}
235
- */
236
- async deleteMany(query) {
237
- return axios.delete(baseURL, {
238
- data: query
239
- });
240
- },
241
- /**
242
- * Create multiple entities in a single request
243
- * @param {Array} data - Array of entity data
244
- * @returns {Promise<Array>} Created entities
245
- */
246
- async bulkCreate(data) {
247
- return axios.post(`${baseURL}/bulk`, data);
248
- },
249
- /**
250
- * Import entities from a file
251
- * @param {File} file - File to import
252
- * @returns {Promise<Object>} Import result
253
- */
254
- async importEntities(file) {
255
- const formData = new FormData();
256
- formData.append('file', file, file.name);
257
- return axios.post(`${baseURL}/import`, formData, {
258
- headers: {
259
- 'Content-Type': 'multipart/form-data'
260
- }
261
- });
262
- }
263
- };
264
- }
265
-
266
- /**
267
- * Creates the integrations module for the Base44 SDK
268
- * @param {import('axios').AxiosInstance} axios - Axios instance
269
- * @param {string|number} appId - Application ID
270
- * @returns {Object} Integrations module
271
- */
272
- function createIntegrationsModule(axios, appId) {
273
- // Using nested Proxy objects to handle dynamic package and endpoint names
274
- return new Proxy({}, {
275
- get(target, packageName) {
276
- // Skip internal properties
277
- if (typeof packageName !== 'string' || packageName === 'then' || packageName.startsWith('_')) {
278
- return undefined;
279
- }
280
-
281
- // Create a proxy for integration endpoints
282
- return new Proxy({}, {
283
- get(target, endpointName) {
284
- // Skip internal properties
285
- if (typeof endpointName !== 'string' || endpointName === 'then' || endpointName.startsWith('_')) {
286
- return undefined;
287
- }
288
-
289
- // Return a function that calls the integration endpoint
290
- return async data => {
291
- // Validate input
292
- if (typeof data === 'string') {
293
- throw new Error(`Integration ${endpointName} must receive an object with named parameters, received: ${data}`);
294
- }
295
- let formData;
296
- let contentType;
297
-
298
- // Handle file uploads with FormData
299
- if (data instanceof FormData || data && Object.values(data).some(value => value instanceof File)) {
300
- formData = new FormData();
301
- Object.keys(data).forEach(key => {
302
- if (data[key] instanceof File) {
303
- formData.append(key, data[key], data[key].name);
304
- } else if (typeof data[key] === 'object' && data[key] !== null) {
305
- formData.append(key, JSON.stringify(data[key]));
306
- } else {
307
- formData.append(key, data[key]);
308
- }
309
- });
310
- contentType = 'multipart/form-data';
311
- } else {
312
- formData = data;
313
- contentType = 'application/json';
314
- }
315
-
316
- // For Core package
317
- if (packageName === 'Core') {
318
- return axios.post(`/apps/${appId}/integrations/Core/${endpointName}`, formData || data, {
319
- headers: {
320
- 'Content-Type': contentType
321
- }
322
- });
323
- }
324
-
325
- // For other packages
326
- return axios.post(`/apps/${appId}/integrations/installable/${packageName}/integration-endpoints/${endpointName}`, formData || data, {
327
- headers: {
328
- 'Content-Type': contentType
329
- }
330
- });
331
- };
332
- }
333
- });
334
- }
335
- });
336
- }
337
-
338
- /**
339
- * Creates the auth module for the Base44 SDK
340
- * @param {import('axios').AxiosInstance} axios - Axios instance
341
- * @param {string|number} appId - Application ID
342
- * @param {string} serverUrl - Server URL
343
- * @returns {Object} Auth module with authentication methods
344
- */
345
- function createAuthModule(axios, appId, serverUrl) {
346
- return {
347
- /**
348
- * Get current user information
349
- * @returns {Promise<Object>} Current user data
350
- */
351
- async me() {
352
- return axios.get(`/apps/${appId}/entities/User/me`);
353
- },
354
- /**
355
- * Update current user data
356
- * @param {Object} data - Updated user data
357
- * @returns {Promise<Object>} Updated user
358
- */
359
- async updateMe(data) {
360
- return axios.put(`/apps/${appId}/entities/User/me`, data);
361
- },
362
- /**
363
- * Redirects the user to the Base44 login page
364
- * @param {string} nextUrl - URL to redirect to after successful login
365
- * @throws {Error} When not in a browser environment
366
- */
367
- login(nextUrl) {
368
- // This function only works in a browser environment
369
- if (typeof window === 'undefined') {
370
- throw new Error('Login method can only be used in a browser environment');
371
- }
372
-
373
- // If nextUrl is not provided, use the current URL
374
- const redirectUrl = nextUrl || window.location.href;
375
-
376
- // Build the login URL
377
- const loginUrl = `${serverUrl}/login?from_url=${encodeURIComponent(redirectUrl)}&app_id=${appId}`;
378
-
379
- // Redirect to the login page
380
- window.location.href = loginUrl;
381
- },
382
- /**
383
- * Logout the current user
384
- * Removes the token from localStorage and optionally redirects to a URL
385
- * @param {string} [redirectUrl] - Optional URL to redirect to after logout
386
- * @returns {Promise<void>}
387
- */
388
- async logout(redirectUrl) {
389
- // Remove token from axios headers
390
- delete axios.defaults.headers.common['Authorization'];
391
-
392
- // Remove token from localStorage
393
- if (typeof window !== 'undefined' && window.localStorage) {
394
- try {
395
- window.localStorage.removeItem('base44_access_token');
396
- } catch (e) {
397
- console.error('Failed to remove token from localStorage:', e);
398
- }
399
- }
400
-
401
- // Redirect if a URL is provided
402
- if (redirectUrl && typeof window !== 'undefined') {
403
- window.location.href = redirectUrl;
404
- }
405
- return Promise.resolve();
406
- },
407
- /**
408
- * Set authentication token
409
- * @param {string} token - Auth token
410
- * @param {boolean} [saveToStorage=true] - Whether to save the token to localStorage
411
- */
412
- setToken(token) {
413
- let saveToStorage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
414
- if (!token) return;
415
- axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
416
-
417
- // Save token to localStorage if requested
418
- if (saveToStorage && typeof window !== 'undefined' && window.localStorage) {
419
- try {
420
- window.localStorage.setItem('base44_access_token', token);
421
- } catch (e) {
422
- console.error('Failed to save token to localStorage:', e);
423
- }
424
- }
425
- },
426
- /**
427
- * Verify if the current token is valid
428
- * @returns {Promise<boolean>} True if token is valid
429
- */
430
- async isAuthenticated() {
431
- try {
432
- await this.me();
433
- return true;
434
- } catch (error) {
435
- return false;
436
- }
437
- }
438
- };
439
- }
440
-
441
- /**
442
- * Utility functions for authentication and token handling
443
- */
444
-
445
- /**
446
- * Retrieves an access token from either localStorage or URL parameters
447
- *
448
- * @param {Object} options - Configuration options
449
- * @param {string} [options.storageKey='base44_access_token'] - The key to use in localStorage
450
- * @param {string} [options.paramName='access_token'] - The URL parameter name
451
- * @param {boolean} [options.saveToStorage=true] - Whether to save the token to localStorage if found in URL
452
- * @param {boolean} [options.removeFromUrl=true] - Whether to remove the token from URL after retrieval
453
- * @returns {string|null} The access token or null if not found
454
- */
455
- function getAccessToken() {
456
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
457
- const {
458
- storageKey = 'base44_access_token',
459
- paramName = 'access_token',
460
- saveToStorage = true,
461
- removeFromUrl = true
462
- } = options;
463
- let token = null;
464
-
465
- // Try to get token from URL parameters
466
- if (typeof window !== 'undefined' && window.location) {
467
- try {
468
- const urlParams = new URLSearchParams(window.location.search);
469
- token = urlParams.get(paramName);
470
-
471
- // If token found in URL
472
- if (token) {
473
- // Save token to localStorage if requested
474
- if (saveToStorage) {
475
- saveAccessToken(token, {
476
- storageKey
477
- });
478
- }
479
-
480
- // Remove token from URL for security if requested
481
- if (removeFromUrl) {
482
- urlParams.delete(paramName);
483
- const newUrl = `${window.location.pathname}${urlParams.toString() ? `?${urlParams.toString()}` : ''}${window.location.hash}`;
484
- window.history.replaceState({}, document.title, newUrl);
485
- }
486
- return token;
487
- }
488
- } catch (e) {
489
- console.error('Error retrieving token from URL:', e);
490
- }
491
- }
492
-
493
- // If no token in URL, try localStorage
494
- if (typeof window !== 'undefined' && window.localStorage) {
495
- try {
496
- token = window.localStorage.getItem(storageKey);
497
- return token;
498
- } catch (e) {
499
- console.error('Error retrieving token from localStorage:', e);
500
- }
501
- }
502
- return null;
503
- }
504
-
505
- /**
506
- * Saves an access token to localStorage
507
- *
508
- * @param {string} token - The access token to save
509
- * @param {Object} options - Configuration options
510
- * @param {string} [options.storageKey='base44_access_token'] - The key to use in localStorage
511
- * @returns {boolean} Success status
512
- */
513
- function saveAccessToken(token) {
514
- let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
515
- const {
516
- storageKey = 'base44_access_token'
517
- } = options;
518
- if (typeof window === 'undefined' || !window.localStorage || !token) {
519
- return false;
520
- }
521
- try {
522
- window.localStorage.setItem(storageKey, token);
523
- return true;
524
- } catch (e) {
525
- console.error('Error saving token to localStorage:', e);
526
- return false;
527
- }
528
- }
529
-
530
- /**
531
- * Removes the access token from localStorage
532
- *
533
- * @param {Object} options - Configuration options
534
- * @param {string} [options.storageKey='base44_access_token'] - The key to use in localStorage
535
- * @returns {boolean} Success status
536
- */
537
- function removeAccessToken() {
538
- let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
539
- const {
540
- storageKey = 'base44_access_token'
541
- } = options;
542
- if (typeof window === 'undefined' || !window.localStorage) {
543
- return false;
544
- }
545
- try {
546
- window.localStorage.removeItem(storageKey);
547
- return true;
548
- } catch (e) {
549
- console.error('Error removing token from localStorage:', e);
550
- return false;
551
- }
552
- }
553
-
554
- /**
555
- * Constructs the absolute URL for the login page
556
- *
557
- * @param {string} nextUrl - URL to redirect back to after login
558
- * @param {Object} options - Configuration options
559
- * @param {string} options.serverUrl - Server URL (e.g., 'https://app.base44.com')
560
- * @param {string|number} options.appId - Application ID
561
- * @param {string} [options.loginPath='/login'] - Path to the login endpoint
562
- * @returns {string} The complete login URL
563
- */
564
- function getLoginUrl(nextUrl, options) {
565
- const {
566
- serverUrl,
567
- appId,
568
- loginPath = '/login'
569
- } = options;
570
- if (!serverUrl || !appId) {
571
- throw new Error('serverUrl and appId are required to construct login URL');
572
- }
573
- const encodedRedirectUrl = encodeURIComponent(nextUrl || (typeof window !== 'undefined' ? window.location.href : ''));
574
- return `${serverUrl}${loginPath}?from_url=${encodedRedirectUrl}&app_id=${appId}`;
575
- }
576
-
577
- /**
578
- * Create a Base44 client instance
579
- * @param {Object} config - Client configuration
580
- * @param {string} [config.serverUrl='https://app.base44.com'] - API server URL
581
- * @param {string|number} config.appId - Application ID
582
- * @param {string} [config.env='prod'] - Environment ('prod' or 'dev')
583
- * @param {string} [config.token] - Authentication token
584
- * @param {boolean} [config.requiresAuth=false] - Whether the app requires authentication
585
- * @returns {Object} Base44 client instance
586
- */
587
- function createClient(config) {
588
- if (!config || !config.appId) {
589
- throw new Error('appId is required');
590
- }
591
- const {
592
- serverUrl = 'https://app.base44.com',
593
- appId,
594
- env = 'prod',
595
- token,
596
- requiresAuth = false
597
- } = config;
598
- console.log("DOES IT?", requiresAuth, typeof window !== 'undefined');
599
-
600
- // Create the base axios client
601
- const axiosClient = createAxiosClient({
602
- baseURL: `${serverUrl}/api`,
603
- headers: {
604
- 'X-App-Id': String(appId),
605
- 'X-Environment': env
606
- },
607
- token,
608
- requiresAuth,
609
- // Pass requiresAuth to axios client
610
- appId,
611
- // Pass appId for login redirect
612
- serverUrl // Pass serverUrl for login redirect
613
- });
614
-
615
- // Create modules
616
- const entities = createEntitiesModule(axiosClient, appId);
617
- const integrations = createIntegrationsModule(axiosClient, appId);
618
- const auth = createAuthModule(axiosClient, appId, serverUrl);
619
-
620
- // Always try to get token from localStorage or URL parameters
621
- if (typeof window !== 'undefined') {
622
- // Get token from URL or localStorage
623
- const accessToken = token || getAccessToken();
624
- if (accessToken) {
625
- auth.setToken(accessToken);
626
- }
627
- }
628
-
629
- // If authentication is required, verify token and redirect to login if needed
630
- if (requiresAuth && typeof window !== 'undefined') {
631
- // We perform this check asynchronously to not block client creation
632
- setTimeout(async () => {
633
- try {
634
- const isAuthenticated = await auth.isAuthenticated();
635
- if (!isAuthenticated) {
636
- auth.login(window.location.href);
637
- }
638
- } catch (error) {
639
- console.error('Authentication check failed:', error);
640
- auth.login(window.location.href);
641
- }
642
- }, 0);
643
- }
644
-
645
- // Assemble and return the client
646
- return {
647
- entities,
648
- integrations,
649
- auth,
650
- /**
651
- * Set authentication token for all requests
652
- * @param {string} newToken - New auth token
653
- */
654
- setToken(newToken) {
655
- auth.setToken(newToken);
656
- },
657
- /**
658
- * Get current configuration
659
- * @returns {Object} Current configuration
660
- */
661
- getConfig() {
662
- return {
663
- serverUrl,
664
- appId,
665
- env,
666
- requiresAuth
667
- };
668
- }
669
- };
670
- }
671
-
672
- export { Base44Error, createClient, getAccessToken, getLoginUrl, removeAccessToken, saveAccessToken };
1
+ import e from"axios";class t extends Error{constructor(e,t,o,n,r){super(e),this.name="Base44Error",this.status=t,this.code=o,this.data=n,this.originalError=r}toJSON(){return{name:this.name,message:this.message,status:this.status,code:this.code,data:this.data}}}function o(o){let{baseURL:n,headers:r={},token:a,requiresAuth:i=!1,appId:s,serverUrl:c}=o;const d=e.create({baseURL:n,headers:{"Content-Type":"application/json",Accept:"application/json",...r}});return a&&(d.defaults.headers.common.Authorization=`Bearer ${a}`),d.interceptors.request.use((e=>("undefined"!=typeof window&&(e.headers={...e.headers,"X-Origin-URL":window.location.href}),e))),d.interceptors.response.use((e=>e.data),(e=>{const o=e.response?.data?.message||e.response?.data?.detail||e.message,n=new t(o,e.response?.status,e.response?.data?.code,e.response?.data,e);return"production"!==process.env.NODE_ENV&&function(e,o){if(o instanceof t){if(console.error(`${e} ${o.status}: ${o.message}`),o.data)try{console.error("Error data:",JSON.stringify(o.data,null,2))}catch(e){console.error("Error data: [Cannot stringify error data]")}}else console.error(`${e} ${o.message}`)}("[Base44 SDK Error]",n),console.log(i,e.response?.status,"undefined"!=typeof window),i&&403===e.response?.status&&"undefined"!=typeof window&&(console.log("Authentication required. Redirecting to login..."),setTimeout((()=>{!function(e,t){if("undefined"==typeof window)return;const o=`${e}/login?from_url=${encodeURIComponent(window.location.href)}&app_id=${t}`;window.location.href=o}(c,s)}),100)),Promise.reject(n)})),d}function n(e,t){return new Proxy({},{get(o,n){if("string"==typeof n&&"then"!==n&&!n.startsWith("_"))return function(e,t,o){const n=`/apps/${t}/entities/${o}`;return{async list(t,o,r,a){const i={};return t&&(i.sort=t),o&&(i.limit=o),r&&(i.skip=r),a&&(i.fields=Array.isArray(a)?a.join(","):a),e.get(n,{params:i})},async filter(t,o,r,a,i){const s={q:JSON.stringify(t)};return o&&(s.sort=o),r&&(s.limit=r),a&&(s.skip=a),i&&(s.fields=Array.isArray(i)?i.join(","):i),e.get(n,{params:s})},get:async t=>e.get(`${n}/${t}`),create:async t=>e.post(n,t),update:async(t,o)=>e.put(`${n}/${t}`,o),delete:async t=>e.delete(`${n}/${t}`),deleteMany:async t=>e.delete(n,{data:t}),bulkCreate:async t=>e.post(`${n}/bulk`,t),async importEntities(t){const o=new FormData;return o.append("file",t,t.name),e.post(`${n}/import`,o,{headers:{"Content-Type":"multipart/form-data"}})}}}(e,t,n)}})}function r(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};const{storageKey:t="base44_access_token",paramName:o="access_token",saveToStorage:n=!0,removeFromUrl:r=!0}=e;let i=null;if("undefined"!=typeof window&&window.location)try{const e=new URLSearchParams(window.location.search);if(i=e.get(o),i){if(n&&a(i,{storageKey:t}),r){e.delete(o);const t=`${window.location.pathname}${e.toString()?`?${e.toString()}`:""}${window.location.hash}`;window.history.replaceState({},document.title,t)}return i}}catch(e){console.error("Error retrieving token from URL:",e)}if("undefined"!=typeof window&&window.localStorage)try{return i=window.localStorage.getItem(t),i}catch(e){console.error("Error retrieving token from localStorage:",e)}return null}function a(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const{storageKey:o="base44_access_token"}=t;if("undefined"==typeof window||!window.localStorage||!e)return!1;try{return window.localStorage.setItem(o,e),!0}catch(e){return console.error("Error saving token to localStorage:",e),!1}}function i(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};const{storageKey:t="base44_access_token"}=e;if("undefined"==typeof window||!window.localStorage)return!1;try{return window.localStorage.removeItem(t),!0}catch(e){return console.error("Error removing token from localStorage:",e),!1}}function s(e,t){const{serverUrl:o,appId:n,loginPath:r="/login"}=t;if(!o||!n)throw new Error("serverUrl and appId are required to construct login URL");return`${o}${r}?from_url=${encodeURIComponent(e||("undefined"!=typeof window?window.location.href:""))}&app_id=${n}`}function c(e){if(!e||!e.appId)throw new Error("appId is required");const{serverUrl:t="https://base44.app",appId:a,env:i="prod",token:s,requiresAuth:c=!1}=e,d=o({baseURL:`${t}/api`,headers:{"X-App-Id":String(a),"X-Environment":i},token:s,requiresAuth:c,appId:a,serverUrl:t}),l=n(d,a),p=function(e,t){return new Proxy({},{get(o,n){if("string"==typeof n&&"then"!==n&&!n.startsWith("_"))return new Proxy({},{get(o,r){if("string"==typeof r&&"then"!==r&&!r.startsWith("_"))return async o=>{if("string"==typeof o)throw new Error(`Integration ${r} must receive an object with named parameters, received: ${o}`);let a,i;return o instanceof FormData||o&&Object.values(o).some((e=>e instanceof File))?(a=new FormData,Object.keys(o).forEach((e=>{o[e]instanceof File?a.append(e,o[e],o[e].name):"object"==typeof o[e]&&null!==o[e]?a.append(e,JSON.stringify(o[e])):a.append(e,o[e])})),i="multipart/form-data"):(a=o,i="application/json"),"Core"===n?e.post(`/apps/${t}/integration-endpoints/Core/${r}`,a||o,{headers:{"Content-Type":i}}):e.post(`/apps/${t}/integration-endpoints/installable/${n}/integration-endpoints/${r}`,a||o,{headers:{"Content-Type":i}})}}})}})}(d,a),u=function(e,t,o){return{me:async()=>e.get(`/apps/${t}/entities/User/me`),updateMe:async o=>e.put(`/apps/${t}/entities/User/me`,o),login(e){if("undefined"==typeof window)throw new Error("Login method can only be used in a browser environment");const n=e||window.location.href,r=`${o}/login?from_url=${encodeURIComponent(n)}&app_id=${t}`;window.location.href=r},async logout(t){if(delete e.defaults.headers.common.Authorization,"undefined"!=typeof window&&window.localStorage)try{window.localStorage.removeItem("base44_access_token")}catch(e){console.error("Failed to remove token from localStorage:",e)}return t&&"undefined"!=typeof window&&(window.location.href=t),Promise.resolve()},setToken(t){let o=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(t&&(e.defaults.headers.common.Authorization=`Bearer ${t}`,o&&"undefined"!=typeof window&&window.localStorage))try{window.localStorage.setItem("base44_access_token",t)}catch(e){console.error("Failed to save token to localStorage:",e)}},async isAuthenticated(){try{return await this.me(),!0}catch(e){return!1}}}}(d,a,t);if("undefined"!=typeof window){const e=s||r();e&&u.setToken(e)}return c&&"undefined"!=typeof window&&setTimeout((async()=>{try{await u.isAuthenticated()||u.login(window.location.href)}catch(e){console.error("Authentication check failed:",e),u.login(window.location.href)}}),0),{entities:l,integrations:p,auth:u,setToken(e){u.setToken(e)},getConfig:()=>({serverUrl:t,appId:a,env:i,requiresAuth:c})}}export{t as Base44Error,c as createClient,r as getAccessToken,s as getLoginUrl,i as removeAccessToken,a as saveAccessToken};