@base44/sdk 0.1.1 → 0.2.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.
package/README.md CHANGED
@@ -19,7 +19,7 @@ import { createClient } from '@base44/sdk';
19
19
 
20
20
  // Create a client instance
21
21
  const base44 = createClient({
22
- serverUrl: 'https://app.base44.com', // Optional, defaults to 'https://app.base44.com'
22
+ serverUrl: 'https://base44.app', // Optional, defaults to 'https://base44.app'
23
23
  appId: 'your-app-id', // Required
24
24
  env: 'prod', // Optional, defaults to 'prod'
25
25
  token: 'your-token', // Optional
@@ -126,7 +126,7 @@ import { getAccessToken, saveAccessToken, removeAccessToken } from '@base44/sdk/
126
126
  const base44 = createClient({ appId: 'your-app-id' });
127
127
 
128
128
  // Redirect to the login page
129
- // This will redirect to: app.base44.com/login?from_url=http://your-app.com/dashboard&app_id=your-app-id
129
+ // This will redirect to: base44.app/login?from_url=http://your-app.com/dashboard&app_id=your-app-id
130
130
  function handleLogin() {
131
131
  base44.auth.login('/dashboard');
132
132
  }
@@ -483,7 +483,7 @@ E2E tests require access to a Base44 API. To run these tests:
483
483
  1. Copy `tests/.env.example` to `tests/.env`
484
484
  2. Fill in your Base44 API credentials in the `.env` file:
485
485
  ```
486
- BASE44_SERVER_URL=https://app.base44.com
486
+ BASE44_SERVER_URL=https://base44.app
487
487
  BASE44_APP_ID=your_app_id_here
488
488
  BASE44_AUTH_TOKEN=your_auth_token_here
489
489
  ```
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Create a Base44 client instance
3
+ * @param {Object} config - Client configuration
4
+ * @param {string} [config.serverUrl='https://base44.app'] - API server URL
5
+ * @param {string|number} config.appId - Application ID
6
+ * @param {string} [config.env='prod'] - Environment ('prod' or 'dev')
7
+ * @param {string} [config.token] - Authentication token
8
+ * @param {boolean} [config.requiresAuth=false] - Whether the app requires authentication
9
+ * @returns {Object} Base44 client instance
10
+ */
11
+ export declare function createClient(config: {
12
+ serverUrl?: string;
13
+ appId: string;
14
+ env?: string;
15
+ token?: string;
16
+ requiresAuth?: boolean;
17
+ }): {
18
+ entities: {};
19
+ integrations: {};
20
+ auth: {
21
+ me(): Promise<import("axios").AxiosResponse<any, any>>;
22
+ updateMe(data: Record<string, any>): Promise<import("axios").AxiosResponse<any, any>>;
23
+ login(nextUrl: string): void;
24
+ logout(redirectUrl?: string): void;
25
+ setToken(token: string, saveToStorage?: boolean): void;
26
+ loginViaUsernamePassword(email: string, password: string, turnstileToken?: string): Promise<{
27
+ access_token: string;
28
+ user: any;
29
+ }>;
30
+ isAuthenticated(): Promise<boolean>;
31
+ };
32
+ functions: {
33
+ invoke(functionName: string, data: Record<string, any>): Promise<import("axios").AxiosResponse<any, any>>;
34
+ };
35
+ /**
36
+ * Set authentication token for all requests
37
+ * @param {string} newToken - New auth token
38
+ */
39
+ setToken(newToken: string): void;
40
+ /**
41
+ * Get current configuration
42
+ * @returns {Object} Current configuration
43
+ */
44
+ getConfig(): {
45
+ serverUrl: string;
46
+ appId: string;
47
+ env: string;
48
+ requiresAuth: boolean;
49
+ };
50
+ };
package/dist/client.js ADDED
@@ -0,0 +1,98 @@
1
+ import { createAxiosClient } from "./utils/axios-client.js";
2
+ import { createEntitiesModule } from "./modules/entities.js";
3
+ import { createIntegrationsModule } from "./modules/integrations.js";
4
+ import { createAuthModule } from "./modules/auth.js";
5
+ import { getAccessToken } from "./utils/auth-utils.js";
6
+ import { createFunctionsModule } from "./modules/functions.js";
7
+ /**
8
+ * Create a Base44 client instance
9
+ * @param {Object} config - Client configuration
10
+ * @param {string} [config.serverUrl='https://base44.app'] - API server URL
11
+ * @param {string|number} config.appId - Application ID
12
+ * @param {string} [config.env='prod'] - Environment ('prod' or 'dev')
13
+ * @param {string} [config.token] - Authentication token
14
+ * @param {boolean} [config.requiresAuth=false] - Whether the app requires authentication
15
+ * @returns {Object} Base44 client instance
16
+ */
17
+ export function createClient(config) {
18
+ const { serverUrl = "https://base44.app", appId, env = "prod", token, requiresAuth = false, } = config;
19
+ // Create the base axios client
20
+ const axiosClient = createAxiosClient({
21
+ baseURL: `${serverUrl}/api`,
22
+ headers: {
23
+ "X-App-Id": String(appId),
24
+ "X-Environment": env,
25
+ },
26
+ token,
27
+ requiresAuth, // Pass requiresAuth to axios client
28
+ appId, // Pass appId for login redirect
29
+ serverUrl, // Pass serverUrl for login redirect
30
+ });
31
+ const functionsAxiosClient = createAxiosClient({
32
+ baseURL: `${serverUrl}/api`,
33
+ headers: {
34
+ "X-App-Id": String(appId),
35
+ "X-Environment": env,
36
+ },
37
+ token,
38
+ requiresAuth,
39
+ appId,
40
+ serverUrl,
41
+ interceptResponses: false,
42
+ });
43
+ // Create modules
44
+ const entities = createEntitiesModule(axiosClient, appId);
45
+ const integrations = createIntegrationsModule(axiosClient, appId);
46
+ const auth = createAuthModule(axiosClient, appId, serverUrl);
47
+ const functions = createFunctionsModule(functionsAxiosClient, appId);
48
+ // Always try to get token from localStorage or URL parameters
49
+ if (typeof window !== "undefined") {
50
+ // Get token from URL or localStorage
51
+ const accessToken = token || getAccessToken();
52
+ if (accessToken) {
53
+ auth.setToken(accessToken);
54
+ }
55
+ }
56
+ // If authentication is required, verify token and redirect to login if needed
57
+ if (requiresAuth && typeof window !== "undefined") {
58
+ // We perform this check asynchronously to not block client creation
59
+ setTimeout(async () => {
60
+ try {
61
+ const isAuthenticated = await auth.isAuthenticated();
62
+ if (!isAuthenticated) {
63
+ auth.login(window.location.href);
64
+ }
65
+ }
66
+ catch (error) {
67
+ console.error("Authentication check failed:", error);
68
+ auth.login(window.location.href);
69
+ }
70
+ }, 0);
71
+ }
72
+ // Assemble and return the client
73
+ return {
74
+ entities,
75
+ integrations,
76
+ auth,
77
+ functions,
78
+ /**
79
+ * Set authentication token for all requests
80
+ * @param {string} newToken - New auth token
81
+ */
82
+ setToken(newToken) {
83
+ auth.setToken(newToken);
84
+ },
85
+ /**
86
+ * Get current configuration
87
+ * @returns {Object} Current configuration
88
+ */
89
+ getConfig() {
90
+ return {
91
+ serverUrl,
92
+ appId,
93
+ env,
94
+ requiresAuth,
95
+ };
96
+ },
97
+ };
98
+ }
package/dist/index.d.ts CHANGED
@@ -1,86 +1,4 @@
1
- export interface ClientConfig {
2
- serverUrl?: string;
3
- appId: string | number;
4
- env?: 'prod' | 'dev';
5
- token?: string;
6
- requiresAuth?: boolean;
7
- }
8
-
9
- export interface Entity {
10
- id: string;
11
- [key: string]: any;
12
- }
13
-
14
- export interface FilterOptions {
15
- sort?: string;
16
- limit?: number;
17
- skip?: number;
18
- fields?: string[] | string;
19
- }
20
-
21
- export interface EntityMethods {
22
- list(sort?: string, limit?: number, skip?: number, fields?: string[] | string): Promise<Entity[]>;
23
- filter(query: any, sort?: string, limit?: number, skip?: number, fields?: string[] | string): Promise<Entity[]>;
24
- get(id: string): Promise<Entity>;
25
- create(data: Record<string, any>): Promise<Entity>;
26
- update(id: string, data: Record<string, any>): Promise<Entity>;
27
- delete(id: string): Promise<void>;
28
- deleteMany(query: Record<string, any>): Promise<void>;
29
- bulkCreate(data: Record<string, any>[]): Promise<Entity[]>;
30
- importEntities(file: File): Promise<any>;
31
- }
32
-
33
- export interface EntitiesModule {
34
- [entityName: string]: EntityMethods;
35
- }
36
-
37
- export interface IntegrationEndpoint {
38
- (data: Record<string, any>): Promise<any>;
39
- }
40
-
41
- export interface IntegrationsPackage {
42
- [endpointName: string]: IntegrationEndpoint;
43
- }
44
-
45
- export interface IntegrationsModule {
46
- [packageName: string]: IntegrationsPackage;
47
- }
48
-
49
- export interface AuthModule {
50
- me(): Promise<Entity>;
51
- updateMe(data: Record<string, any>): Promise<Entity>;
52
- login(nextUrl?: string): void;
53
- logout(redirectUrl?: string): Promise<void>;
54
- setToken(token: string, saveToStorage?: boolean): void;
55
- isAuthenticated(): Promise<boolean>;
56
- }
57
-
58
- export interface Base44Client {
59
- entities: EntitiesModule;
60
- integrations: IntegrationsModule;
61
- auth: AuthModule;
62
- setToken(token: string): void;
63
- getConfig(): {
64
- serverUrl: string;
65
- appId: string | number;
66
- env: string;
67
- requiresAuth: boolean;
68
- };
69
- }
70
-
71
- export class Base44Error extends Error {
72
- status?: number;
73
- code?: string;
74
- data?: any;
75
- originalError?: Error;
76
-
77
- constructor(
78
- message: string,
79
- status?: number,
80
- code?: string,
81
- data?: any,
82
- originalError?: Error
83
- );
84
- }
85
-
86
- export function createClient(config: ClientConfig): Base44Client;
1
+ import { createClient } from "./client.js";
2
+ import { Base44Error } from "./utils/axios-client.js";
3
+ import { getAccessToken, saveAccessToken, removeAccessToken, getLoginUrl } from "./utils/auth-utils.js";
4
+ export { createClient, Base44Error, getAccessToken, saveAccessToken, removeAccessToken, getLoginUrl, };
package/dist/index.js CHANGED
@@ -1 +1,6 @@
1
- "use strict";var e=require("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:s=!1,appId:i,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(s,e.response?.status,"undefined"!=typeof window),s&&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,i)}),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 s={};return t&&(s.sort=t),o&&(s.limit=o),r&&(s.skip=r),a&&(s.fields=Array.isArray(a)?a.join(","):a),e.get(n,{params:s})},async filter(t,o,r,a,s){const i={q:JSON.stringify(t)};return o&&(i.sort=o),r&&(i.limit=r),a&&(i.skip=a),s&&(i.fields=Array.isArray(s)?s.join(","):s),e.get(n,{params:i})},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 s=null;if("undefined"!=typeof window&&window.location)try{const e=new URLSearchParams(window.location.search);if(s=e.get(o),s){if(n&&a(s,{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 s}}catch(e){console.error("Error retrieving token from URL:",e)}if("undefined"!=typeof window&&window.localStorage)try{return s=window.localStorage.getItem(t),s}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}}exports.Base44Error=t,exports.createClient=function(e){if(!e||!e.appId)throw new Error("appId is required");const{serverUrl:t="https://app.base44.com",appId:a,env:s="prod",token:i,requiresAuth:c=!1}=e;console.log("DOES IT?",c,"undefined"!=typeof window);const d=o({baseURL:`${t}/api`,headers:{"X-App-Id":String(a),"X-Environment":s},token:i,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,s;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])})),s="multipart/form-data"):(a=o,s="application/json"),"Core"===n?e.post(`/apps/${t}/integrations/Core/${r}`,a||o,{headers:{"Content-Type":s}}):e.post(`/apps/${t}/integrations/installable/${n}/integration-endpoints/${r}`,a||o,{headers:{"Content-Type":s}})}}})}})}(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=i||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:s,requiresAuth:c})}},exports.getAccessToken=r,exports.getLoginUrl=function(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}`},exports.removeAccessToken=function(){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}},exports.saveAccessToken=a;
1
+ import { createClient } from "./client.js";
2
+ import { Base44Error } from "./utils/axios-client.js";
3
+ import { getAccessToken, saveAccessToken, removeAccessToken, getLoginUrl, } from "./utils/auth-utils.js";
4
+ export { createClient, Base44Error,
5
+ // Export auth utilities for easier access
6
+ getAccessToken, saveAccessToken, removeAccessToken, getLoginUrl, };
@@ -0,0 +1,56 @@
1
+ import { AxiosInstance } from "axios";
2
+ /**
3
+ * Creates the auth module for the Base44 SDK
4
+ * @param {import('axios').AxiosInstance} axios - Axios instance
5
+ * @param {string|number} appId - Application ID
6
+ * @param {string} serverUrl - Server URL
7
+ * @returns {Object} Auth module with authentication methods
8
+ */
9
+ export declare function createAuthModule(axios: AxiosInstance, appId: string, serverUrl: string): {
10
+ /**
11
+ * Get current user information
12
+ * @returns {Promise<Object>} Current user data
13
+ */
14
+ me(): Promise<import("axios").AxiosResponse<any, any>>;
15
+ /**
16
+ * Update current user data
17
+ * @param {Object} data - Updated user data
18
+ * @returns {Promise<Object>} Updated user
19
+ */
20
+ updateMe(data: Record<string, any>): Promise<import("axios").AxiosResponse<any, any>>;
21
+ /**
22
+ * Redirects the user to the app's login page
23
+ * @param {string} nextUrl - URL to redirect to after successful login
24
+ * @throws {Error} When not in a browser environment
25
+ */
26
+ login(nextUrl: string): void;
27
+ /**
28
+ * Logout the current user
29
+ * Removes the token from localStorage and optionally redirects to a URL or reloads the page
30
+ * @param redirectUrl - Optional URL to redirect to after logout. Reloads the page if not provided
31
+ * @returns {Promise<void>}
32
+ */
33
+ logout(redirectUrl?: string): void;
34
+ /**
35
+ * Set authentication token
36
+ * @param {string} token - Auth token
37
+ * @param {boolean} [saveToStorage=true] - Whether to save the token to localStorage
38
+ */
39
+ setToken(token: string, saveToStorage?: boolean): void;
40
+ /**
41
+ * Login via username and password
42
+ * @param email - User email
43
+ * @param password - User password
44
+ * @param turnstileToken - Optional Turnstile captcha token
45
+ * @returns Login response with access_token and user
46
+ */
47
+ loginViaUsernamePassword(email: string, password: string, turnstileToken?: string): Promise<{
48
+ access_token: string;
49
+ user: any;
50
+ }>;
51
+ /**
52
+ * Verify if the current token is valid
53
+ * @returns {Promise<boolean>} True if token is valid
54
+ */
55
+ isAuthenticated(): Promise<boolean>;
56
+ };
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Creates the auth module for the Base44 SDK
3
+ * @param {import('axios').AxiosInstance} axios - Axios instance
4
+ * @param {string|number} appId - Application ID
5
+ * @param {string} serverUrl - Server URL
6
+ * @returns {Object} Auth module with authentication methods
7
+ */
8
+ export function createAuthModule(axios, appId, serverUrl) {
9
+ return {
10
+ /**
11
+ * Get current user information
12
+ * @returns {Promise<Object>} Current user data
13
+ */
14
+ async me() {
15
+ return axios.get(`/apps/${appId}/entities/User/me`);
16
+ },
17
+ /**
18
+ * Update current user data
19
+ * @param {Object} data - Updated user data
20
+ * @returns {Promise<Object>} Updated user
21
+ */
22
+ async updateMe(data) {
23
+ return axios.put(`/apps/${appId}/entities/User/me`, data);
24
+ },
25
+ /**
26
+ * Redirects the user to the app's login page
27
+ * @param {string} nextUrl - URL to redirect to after successful login
28
+ * @throws {Error} When not in a browser environment
29
+ */
30
+ login(nextUrl) {
31
+ // This function only works in a browser environment
32
+ if (typeof window === "undefined") {
33
+ throw new Error("Login method can only be used in a browser environment");
34
+ }
35
+ // If nextUrl is not provided, use the current URL
36
+ const redirectUrl = nextUrl || window.location.href;
37
+ // Build the login URL
38
+ const loginUrl = `/login?from_url=${encodeURIComponent(redirectUrl)}`;
39
+ // Redirect to the login page
40
+ window.location.href = loginUrl;
41
+ },
42
+ /**
43
+ * Logout the current user
44
+ * Removes the token from localStorage and optionally redirects to a URL or reloads the page
45
+ * @param redirectUrl - Optional URL to redirect to after logout. Reloads the page if not provided
46
+ * @returns {Promise<void>}
47
+ */
48
+ logout(redirectUrl) {
49
+ // Remove token from axios headers
50
+ delete axios.defaults.headers.common["Authorization"];
51
+ // Remove token from localStorage
52
+ if (typeof window !== "undefined" && window.localStorage) {
53
+ try {
54
+ window.localStorage.removeItem("base44_access_token");
55
+ }
56
+ catch (e) {
57
+ console.error("Failed to remove token from localStorage:", e);
58
+ }
59
+ }
60
+ // Redirect if a URL is provided
61
+ if (typeof window !== "undefined") {
62
+ if (redirectUrl) {
63
+ window.location.href = redirectUrl;
64
+ }
65
+ else {
66
+ window.location.reload();
67
+ }
68
+ }
69
+ },
70
+ /**
71
+ * Set authentication token
72
+ * @param {string} token - Auth token
73
+ * @param {boolean} [saveToStorage=true] - Whether to save the token to localStorage
74
+ */
75
+ setToken(token, saveToStorage = true) {
76
+ if (!token)
77
+ return;
78
+ axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
79
+ // Save token to localStorage if requested
80
+ if (saveToStorage &&
81
+ typeof window !== "undefined" &&
82
+ window.localStorage) {
83
+ try {
84
+ window.localStorage.setItem("base44_access_token", token);
85
+ }
86
+ catch (e) {
87
+ console.error("Failed to save token to localStorage:", e);
88
+ }
89
+ }
90
+ },
91
+ /**
92
+ * Login via username and password
93
+ * @param email - User email
94
+ * @param password - User password
95
+ * @param turnstileToken - Optional Turnstile captcha token
96
+ * @returns Login response with access_token and user
97
+ */
98
+ async loginViaUsernamePassword(email, password, turnstileToken) {
99
+ var _a;
100
+ try {
101
+ const response = await axios.post(`/apps/${appId}/auth/login`, {
102
+ email,
103
+ password,
104
+ ...(turnstileToken && { turnstile_token: turnstileToken }),
105
+ });
106
+ const { access_token, user } = response;
107
+ if (access_token) {
108
+ this.setToken(access_token);
109
+ }
110
+ return {
111
+ access_token,
112
+ user,
113
+ };
114
+ }
115
+ catch (error) {
116
+ // Handle authentication errors and cleanup
117
+ if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 401) {
118
+ await this.logout();
119
+ }
120
+ throw error;
121
+ }
122
+ },
123
+ /**
124
+ * Verify if the current token is valid
125
+ * @returns {Promise<boolean>} True if token is valid
126
+ */
127
+ async isAuthenticated() {
128
+ try {
129
+ await this.me();
130
+ return true;
131
+ }
132
+ catch (error) {
133
+ return false;
134
+ }
135
+ },
136
+ };
137
+ }
@@ -0,0 +1,8 @@
1
+ import { AxiosInstance } from "axios";
2
+ /**
3
+ * Creates the entities module for the Base44 SDK
4
+ * @param {import('axios').AxiosInstance} axios - Axios instance
5
+ * @param {string|number} appId - Application ID
6
+ * @returns {Object} Entities module
7
+ */
8
+ export declare function createEntitiesModule(axios: AxiosInstance, appId: string): {};
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Creates the entities module for the Base44 SDK
3
+ * @param {import('axios').AxiosInstance} axios - Axios instance
4
+ * @param {string|number} appId - Application ID
5
+ * @returns {Object} Entities module
6
+ */
7
+ export function createEntitiesModule(axios, appId) {
8
+ // Using Proxy to dynamically handle entity names
9
+ return new Proxy({}, {
10
+ get(target, entityName) {
11
+ // Don't create handlers for internal properties
12
+ if (typeof entityName !== "string" ||
13
+ entityName === "then" ||
14
+ entityName.startsWith("_")) {
15
+ return undefined;
16
+ }
17
+ // Create entity handler
18
+ return createEntityHandler(axios, appId, entityName);
19
+ },
20
+ });
21
+ }
22
+ /**
23
+ * Creates a handler for a specific entity
24
+ * @param {import('axios').AxiosInstance} axios - Axios instance
25
+ * @param {string|number} appId - Application ID
26
+ * @param {string} entityName - Entity name
27
+ * @returns {Object} Entity handler with CRUD methods
28
+ */
29
+ function createEntityHandler(axios, appId, entityName) {
30
+ const baseURL = `/apps/${appId}/entities/${entityName}`;
31
+ return {
32
+ /**
33
+ * List entities with optional pagination and sorting
34
+ * @param {string} [sort] - Sort parameter
35
+ * @param {number} [limit] - Limit results
36
+ * @param {number} [skip] - Skip results (pagination)
37
+ * @param {string[]} [fields] - Fields to include
38
+ * @returns {Promise<Array>} List of entities
39
+ */
40
+ async list(sort, limit, skip, fields) {
41
+ const params = {};
42
+ if (sort)
43
+ params.sort = sort;
44
+ if (limit)
45
+ params.limit = limit;
46
+ if (skip)
47
+ params.skip = skip;
48
+ if (fields)
49
+ params.fields = Array.isArray(fields) ? fields.join(",") : fields;
50
+ return axios.get(baseURL, { params });
51
+ },
52
+ /**
53
+ * Filter entities based on query
54
+ * @param {Object} query - Filter query
55
+ * @param {string} [sort] - Sort parameter
56
+ * @param {number} [limit] - Limit results
57
+ * @param {number} [skip] - Skip results (pagination)
58
+ * @param {string[]} [fields] - Fields to include
59
+ * @returns {Promise<Array>} Filtered entities
60
+ */
61
+ async filter(query, sort, limit, skip, fields) {
62
+ const params = {
63
+ q: JSON.stringify(query),
64
+ };
65
+ if (sort)
66
+ params.sort = sort;
67
+ if (limit)
68
+ params.limit = limit;
69
+ if (skip)
70
+ params.skip = skip;
71
+ if (fields)
72
+ params.fields = Array.isArray(fields) ? fields.join(",") : fields;
73
+ return axios.get(baseURL, { params });
74
+ },
75
+ /**
76
+ * Get entity by ID
77
+ * @param {string} id - Entity ID
78
+ * @returns {Promise<Object>} Entity
79
+ */
80
+ async get(id) {
81
+ return axios.get(`${baseURL}/${id}`);
82
+ },
83
+ /**
84
+ * Create new entity
85
+ * @param {Object} data - Entity data
86
+ * @returns {Promise<Object>} Created entity
87
+ */
88
+ async create(data) {
89
+ return axios.post(baseURL, data);
90
+ },
91
+ /**
92
+ * Update entity by ID
93
+ * @param {string} id - Entity ID
94
+ * @param {Object} data - Updated entity data
95
+ * @returns {Promise<Object>} Updated entity
96
+ */
97
+ async update(id, data) {
98
+ return axios.put(`${baseURL}/${id}`, data);
99
+ },
100
+ /**
101
+ * Delete entity by ID
102
+ * @param {string} id - Entity ID
103
+ * @returns {Promise<void>}
104
+ */
105
+ async delete(id) {
106
+ return axios.delete(`${baseURL}/${id}`);
107
+ },
108
+ /**
109
+ * Delete multiple entities based on query
110
+ * @param {Object} query - Delete query
111
+ * @returns {Promise<void>}
112
+ */
113
+ async deleteMany(query) {
114
+ return axios.delete(baseURL, { data: query });
115
+ },
116
+ /**
117
+ * Create multiple entities in a single request
118
+ * @param {Array} data - Array of entity data
119
+ * @returns {Promise<Array>} Created entities
120
+ */
121
+ async bulkCreate(data) {
122
+ return axios.post(`${baseURL}/bulk`, data);
123
+ },
124
+ /**
125
+ * Import entities from a file
126
+ * @param {File} file - File to import
127
+ * @returns {Promise<Object>} Import result
128
+ */
129
+ async importEntities(file) {
130
+ const formData = new FormData();
131
+ formData.append("file", file, file.name);
132
+ return axios.post(`${baseURL}/import`, formData, {
133
+ headers: {
134
+ "Content-Type": "multipart/form-data",
135
+ },
136
+ });
137
+ },
138
+ };
139
+ }
@@ -0,0 +1,10 @@
1
+ import { AxiosInstance } from "axios";
2
+ /**
3
+ * Creates the functions module for the Base44 SDK
4
+ * @param {import('axios').AxiosInstance} axios - Axios instance
5
+ * @param {string|number} appId - Application ID
6
+ * @returns {Object} Functions module
7
+ */
8
+ export declare function createFunctionsModule(axios: AxiosInstance, appId: string): {
9
+ invoke(functionName: string, data: Record<string, any>): Promise<import("axios").AxiosResponse<any, any>>;
10
+ };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Creates the functions module for the Base44 SDK
3
+ * @param {import('axios').AxiosInstance} axios - Axios instance
4
+ * @param {string|number} appId - Application ID
5
+ * @returns {Object} Functions module
6
+ */
7
+ export function createFunctionsModule(axios, appId) {
8
+ // Using nested Proxy objects to handle dynamic function names
9
+ return {
10
+ async invoke(functionName, data) {
11
+ // Validate input
12
+ if (typeof data === "string") {
13
+ throw new Error(`Function ${functionName} must receive an object with named parameters, received: ${data}`);
14
+ }
15
+ let formData;
16
+ let contentType;
17
+ // Handle file uploads with FormData
18
+ if (data instanceof FormData ||
19
+ (data && Object.values(data).some((value) => value instanceof File))) {
20
+ formData = new FormData();
21
+ Object.keys(data).forEach((key) => {
22
+ if (data[key] instanceof File) {
23
+ formData.append(key, data[key], data[key].name);
24
+ }
25
+ else if (typeof data[key] === "object" && data[key] !== null) {
26
+ formData.append(key, JSON.stringify(data[key]));
27
+ }
28
+ else {
29
+ formData.append(key, data[key]);
30
+ }
31
+ });
32
+ contentType = "multipart/form-data";
33
+ }
34
+ else {
35
+ formData = data;
36
+ contentType = "application/json";
37
+ }
38
+ return axios.post(`/apps/${appId}/functions/${functionName}`, formData || data, { headers: { "Content-Type": contentType } });
39
+ },
40
+ };
41
+ }
@@ -0,0 +1,8 @@
1
+ import { AxiosInstance } from "axios";
2
+ /**
3
+ * Creates the integrations module for the Base44 SDK
4
+ * @param {import('axios').AxiosInstance} axios - Axios instance
5
+ * @param {string|number} appId - Application ID
6
+ * @returns {Object} Integrations module
7
+ */
8
+ export declare function createIntegrationsModule(axios: AxiosInstance, appId: string): {};
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Creates the integrations module for the Base44 SDK
3
+ * @param {import('axios').AxiosInstance} axios - Axios instance
4
+ * @param {string|number} appId - Application ID
5
+ * @returns {Object} Integrations module
6
+ */
7
+ export function createIntegrationsModule(axios, appId) {
8
+ // Using nested Proxy objects to handle dynamic package and endpoint names
9
+ return new Proxy({}, {
10
+ get(target, packageName) {
11
+ // Skip internal properties
12
+ if (typeof packageName !== "string" ||
13
+ packageName === "then" ||
14
+ packageName.startsWith("_")) {
15
+ return undefined;
16
+ }
17
+ // Create a proxy for integration endpoints
18
+ return new Proxy({}, {
19
+ get(target, endpointName) {
20
+ // Skip internal properties
21
+ if (typeof endpointName !== "string" ||
22
+ endpointName === "then" ||
23
+ endpointName.startsWith("_")) {
24
+ return undefined;
25
+ }
26
+ // Return a function that calls the integration endpoint
27
+ return async (data) => {
28
+ // Validate input
29
+ if (typeof data === "string") {
30
+ throw new Error(`Integration ${endpointName} must receive an object with named parameters, received: ${data}`);
31
+ }
32
+ let formData;
33
+ let contentType;
34
+ // Handle file uploads with FormData
35
+ if (data instanceof FormData ||
36
+ (data &&
37
+ Object.values(data).some((value) => value instanceof File))) {
38
+ formData = new FormData();
39
+ Object.keys(data).forEach((key) => {
40
+ if (data[key] instanceof File) {
41
+ formData.append(key, data[key], data[key].name);
42
+ }
43
+ else if (typeof data[key] === "object" &&
44
+ data[key] !== null) {
45
+ formData.append(key, JSON.stringify(data[key]));
46
+ }
47
+ else {
48
+ formData.append(key, data[key]);
49
+ }
50
+ });
51
+ contentType = "multipart/form-data";
52
+ }
53
+ else {
54
+ formData = data;
55
+ contentType = "application/json";
56
+ }
57
+ // For Core package
58
+ if (packageName === "Core") {
59
+ return axios.post(`/apps/${appId}/integration-endpoints/Core/${endpointName}`, formData || data, { headers: { "Content-Type": contentType } });
60
+ }
61
+ // For other packages
62
+ return axios.post(`/apps/${appId}/integration-endpoints/installable/${packageName}/integration-endpoints/${endpointName}`, formData || data, { headers: { "Content-Type": contentType } });
63
+ };
64
+ },
65
+ });
66
+ },
67
+ });
68
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Utility functions for authentication and token handling
3
+ */
4
+ /**
5
+ * Retrieves an access token from either localStorage or URL parameters
6
+ *
7
+ * @param {Object} options - Configuration options
8
+ * @param {string} [options.storageKey='base44_access_token'] - The key to use in localStorage
9
+ * @param {string} [options.paramName='access_token'] - The URL parameter name
10
+ * @param {boolean} [options.saveToStorage=true] - Whether to save the token to localStorage if found in URL
11
+ * @param {boolean} [options.removeFromUrl=true] - Whether to remove the token from URL after retrieval
12
+ * @returns {string|null} The access token or null if not found
13
+ */
14
+ export declare function getAccessToken(options?: {
15
+ storageKey?: string;
16
+ paramName?: string;
17
+ saveToStorage?: boolean;
18
+ removeFromUrl?: boolean;
19
+ }): string | null;
20
+ /**
21
+ * Saves an access token to localStorage
22
+ *
23
+ * @param {string} token - The access token to save
24
+ * @param {Object} options - Configuration options
25
+ * @param {string} [options.storageKey='base44_access_token'] - The key to use in localStorage
26
+ * @returns {boolean} Success status
27
+ */
28
+ export declare function saveAccessToken(token: string, options: {
29
+ storageKey?: string;
30
+ }): boolean;
31
+ /**
32
+ * Removes the access token from localStorage
33
+ *
34
+ * @param {Object} options - Configuration options
35
+ * @param {string} [options.storageKey='base44_access_token'] - The key to use in localStorage
36
+ * @returns {boolean} Success status
37
+ */
38
+ export declare function removeAccessToken(options: {
39
+ storageKey?: string;
40
+ }): boolean;
41
+ /**
42
+ * Constructs the absolute URL for the login page
43
+ *
44
+ * @param {string} nextUrl - URL to redirect back to after login
45
+ * @param {Object} options - Configuration options
46
+ * @param {string} options.serverUrl - Server URL (e.g., 'https://base44.app')
47
+ * @param {string|number} options.appId - Application ID
48
+ * @param {string} [options.loginPath='/login'] - Path to the login endpoint
49
+ * @returns {string} The complete login URL
50
+ */
51
+ export declare function getLoginUrl(nextUrl: string, options: {
52
+ serverUrl: string;
53
+ appId: string;
54
+ loginPath?: string;
55
+ }): string;
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Utility functions for authentication and token handling
3
+ */
4
+ /**
5
+ * Retrieves an access token from either localStorage or URL parameters
6
+ *
7
+ * @param {Object} options - Configuration options
8
+ * @param {string} [options.storageKey='base44_access_token'] - The key to use in localStorage
9
+ * @param {string} [options.paramName='access_token'] - The URL parameter name
10
+ * @param {boolean} [options.saveToStorage=true] - Whether to save the token to localStorage if found in URL
11
+ * @param {boolean} [options.removeFromUrl=true] - Whether to remove the token from URL after retrieval
12
+ * @returns {string|null} The access token or null if not found
13
+ */
14
+ export function getAccessToken(options = {}) {
15
+ const { storageKey = "base44_access_token", paramName = "access_token", saveToStorage = true, removeFromUrl = true, } = options;
16
+ let token = null;
17
+ // Try to get token from URL parameters
18
+ if (typeof window !== "undefined" && window.location) {
19
+ try {
20
+ const urlParams = new URLSearchParams(window.location.search);
21
+ token = urlParams.get(paramName);
22
+ // If token found in URL
23
+ if (token) {
24
+ // Save token to localStorage if requested
25
+ if (saveToStorage) {
26
+ saveAccessToken(token, { storageKey });
27
+ }
28
+ // Remove token from URL for security if requested
29
+ if (removeFromUrl) {
30
+ urlParams.delete(paramName);
31
+ const newUrl = `${window.location.pathname}${urlParams.toString() ? `?${urlParams.toString()}` : ""}${window.location.hash}`;
32
+ window.history.replaceState({}, document.title, newUrl);
33
+ }
34
+ return token;
35
+ }
36
+ }
37
+ catch (e) {
38
+ console.error("Error retrieving token from URL:", e);
39
+ }
40
+ }
41
+ // If no token in URL, try localStorage
42
+ if (typeof window !== "undefined" && window.localStorage) {
43
+ try {
44
+ token = window.localStorage.getItem(storageKey);
45
+ return token;
46
+ }
47
+ catch (e) {
48
+ console.error("Error retrieving token from localStorage:", e);
49
+ }
50
+ }
51
+ return null;
52
+ }
53
+ /**
54
+ * Saves an access token to localStorage
55
+ *
56
+ * @param {string} token - The access token to save
57
+ * @param {Object} options - Configuration options
58
+ * @param {string} [options.storageKey='base44_access_token'] - The key to use in localStorage
59
+ * @returns {boolean} Success status
60
+ */
61
+ export function saveAccessToken(token, options) {
62
+ const { storageKey = "base44_access_token" } = options;
63
+ if (typeof window === "undefined" || !window.localStorage || !token) {
64
+ return false;
65
+ }
66
+ try {
67
+ window.localStorage.setItem(storageKey, token);
68
+ return true;
69
+ }
70
+ catch (e) {
71
+ console.error("Error saving token to localStorage:", e);
72
+ return false;
73
+ }
74
+ }
75
+ /**
76
+ * Removes the access token from localStorage
77
+ *
78
+ * @param {Object} options - Configuration options
79
+ * @param {string} [options.storageKey='base44_access_token'] - The key to use in localStorage
80
+ * @returns {boolean} Success status
81
+ */
82
+ export function removeAccessToken(options) {
83
+ const { storageKey = "base44_access_token" } = options;
84
+ if (typeof window === "undefined" || !window.localStorage) {
85
+ return false;
86
+ }
87
+ try {
88
+ window.localStorage.removeItem(storageKey);
89
+ return true;
90
+ }
91
+ catch (e) {
92
+ console.error("Error removing token from localStorage:", e);
93
+ return false;
94
+ }
95
+ }
96
+ /**
97
+ * Constructs the absolute URL for the login page
98
+ *
99
+ * @param {string} nextUrl - URL to redirect back to after login
100
+ * @param {Object} options - Configuration options
101
+ * @param {string} options.serverUrl - Server URL (e.g., 'https://base44.app')
102
+ * @param {string|number} options.appId - Application ID
103
+ * @param {string} [options.loginPath='/login'] - Path to the login endpoint
104
+ * @returns {string} The complete login URL
105
+ */
106
+ export function getLoginUrl(nextUrl, options) {
107
+ const { serverUrl, appId, loginPath = "/login" } = options;
108
+ if (!serverUrl || !appId) {
109
+ throw new Error("serverUrl and appId are required to construct login URL");
110
+ }
111
+ const encodedRedirectUrl = encodeURIComponent(nextUrl || (typeof window !== "undefined" ? window.location.href : ""));
112
+ return `${serverUrl}${loginPath}?from_url=${encodedRedirectUrl}&app_id=${appId}`;
113
+ }
@@ -0,0 +1,34 @@
1
+ export declare class Base44Error extends Error {
2
+ status: number;
3
+ code: string;
4
+ data: any;
5
+ originalError: unknown;
6
+ constructor(message: string, status: number, code: string, data: any, originalError: unknown);
7
+ toJSON(): {
8
+ name: string;
9
+ message: string;
10
+ status: number;
11
+ code: string;
12
+ data: any;
13
+ };
14
+ }
15
+ /**
16
+ * Creates an axios client with default configuration and interceptors
17
+ * @param {Object} options - Client configuration options
18
+ * @param {string} options.baseURL - Base URL for all requests
19
+ * @param {Object} options.headers - Additional headers
20
+ * @param {string} options.token - Auth token
21
+ * @param {boolean} options.requiresAuth - Whether the application requires authentication
22
+ * @param {string|number} options.appId - Application ID (needed for login redirect)
23
+ * @param {string} options.serverUrl - Server URL (needed for login redirect)
24
+ * @returns {import('axios').AxiosInstance} Configured axios instance
25
+ */
26
+ export declare function createAxiosClient({ baseURL, headers, token, requiresAuth, appId, serverUrl, interceptResponses, }: {
27
+ baseURL: string;
28
+ headers?: Record<string, string>;
29
+ token?: string;
30
+ requiresAuth?: boolean;
31
+ appId: string;
32
+ serverUrl: string;
33
+ interceptResponses?: boolean;
34
+ }): import("axios").AxiosInstance;
@@ -0,0 +1,114 @@
1
+ import axios from "axios";
2
+ export class Base44Error extends Error {
3
+ constructor(message, status, code, data, originalError) {
4
+ super(message);
5
+ this.name = "Base44Error";
6
+ this.status = status;
7
+ this.code = code;
8
+ this.data = data;
9
+ this.originalError = originalError;
10
+ }
11
+ // Add a method to safely serialize this error without circular references
12
+ toJSON() {
13
+ return {
14
+ name: this.name,
15
+ message: this.message,
16
+ status: this.status,
17
+ code: this.code,
18
+ data: this.data,
19
+ };
20
+ }
21
+ }
22
+ /**
23
+ * Safely logs error information without circular references
24
+ * @param {string} prefix - Prefix for the log message
25
+ * @param {Error} error - The error to log
26
+ */
27
+ function safeErrorLog(prefix, error) {
28
+ if (error instanceof Base44Error) {
29
+ console.error(`${prefix} ${error.status}: ${error.message}`);
30
+ if (error.data) {
31
+ try {
32
+ console.error("Error data:", JSON.stringify(error.data, null, 2));
33
+ }
34
+ catch (e) {
35
+ console.error("Error data: [Cannot stringify error data]");
36
+ }
37
+ }
38
+ }
39
+ else {
40
+ console.error(`${prefix} ${error instanceof Error ? error.message : String(error)}`);
41
+ }
42
+ }
43
+ /**
44
+ * Redirects to the login page with the current URL as return destination
45
+ * @param {string} serverUrl - Base server URL
46
+ * @param {string|number} appId - Application ID
47
+ */
48
+ function redirectToLogin(serverUrl, appId) {
49
+ if (typeof window === "undefined") {
50
+ return; // Can't redirect in non-browser environment
51
+ }
52
+ const currentUrl = encodeURIComponent(window.location.href);
53
+ const loginUrl = `${serverUrl}/login?from_url=${currentUrl}&app_id=${appId}`;
54
+ window.location.href = loginUrl;
55
+ }
56
+ /**
57
+ * Creates an axios client with default configuration and interceptors
58
+ * @param {Object} options - Client configuration options
59
+ * @param {string} options.baseURL - Base URL for all requests
60
+ * @param {Object} options.headers - Additional headers
61
+ * @param {string} options.token - Auth token
62
+ * @param {boolean} options.requiresAuth - Whether the application requires authentication
63
+ * @param {string|number} options.appId - Application ID (needed for login redirect)
64
+ * @param {string} options.serverUrl - Server URL (needed for login redirect)
65
+ * @returns {import('axios').AxiosInstance} Configured axios instance
66
+ */
67
+ export function createAxiosClient({ baseURL, headers = {}, token, requiresAuth = false, appId, serverUrl, interceptResponses = true, }) {
68
+ const client = axios.create({
69
+ baseURL,
70
+ headers: {
71
+ "Content-Type": "application/json",
72
+ Accept: "application/json",
73
+ ...headers,
74
+ },
75
+ });
76
+ // Add token to requests if available
77
+ if (token) {
78
+ client.defaults.headers.common["Authorization"] = `Bearer ${token}`;
79
+ }
80
+ // Add origin URL in browser environment
81
+ client.interceptors.request.use((config) => {
82
+ if (typeof window !== "undefined") {
83
+ config.headers.set("X-Origin-URL", window.location.href);
84
+ }
85
+ return config;
86
+ });
87
+ // Handle responses
88
+ if (interceptResponses) {
89
+ client.interceptors.response.use((response) => response.data, (error) => {
90
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
91
+ const message = ((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) ||
92
+ ((_d = (_c = error.response) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.detail) ||
93
+ error.message;
94
+ const base44Error = new Base44Error(message, (_e = error.response) === null || _e === void 0 ? void 0 : _e.status, (_g = (_f = error.response) === null || _f === void 0 ? void 0 : _f.data) === null || _g === void 0 ? void 0 : _g.code, (_h = error.response) === null || _h === void 0 ? void 0 : _h.data, error);
95
+ // Log errors in development
96
+ if (process.env.NODE_ENV !== "production") {
97
+ safeErrorLog("[Base44 SDK Error]", base44Error);
98
+ }
99
+ // Check for 403 Forbidden (authentication required) and redirect to login if requiresAuth is true
100
+ console.log(requiresAuth, (_j = error.response) === null || _j === void 0 ? void 0 : _j.status, typeof window !== "undefined");
101
+ if (requiresAuth &&
102
+ ((_k = error.response) === null || _k === void 0 ? void 0 : _k.status) === 403 &&
103
+ typeof window !== "undefined") {
104
+ console.log("Authentication required. Redirecting to login...");
105
+ // Use a slight delay to allow the error to propagate first
106
+ setTimeout(() => {
107
+ redirectToLogin(serverUrl, appId);
108
+ }, 100);
109
+ }
110
+ return Promise.reject(base44Error);
111
+ });
112
+ }
113
+ return client;
114
+ }
package/package.json CHANGED
@@ -1,49 +1,36 @@
1
1
  {
2
2
  "name": "@base44/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "JavaScript SDK for Base44 API",
5
5
  "main": "dist/index.js",
6
- "module": "dist/index.esm.js",
7
6
  "types": "dist/index.d.ts",
8
- "browser": "dist/index.umd.js",
9
7
  "type": "module",
10
8
  "files": [
11
9
  "dist"
12
10
  ],
13
11
  "scripts": {
14
- "build": "rollup -c && npm run copy:types",
15
- "build:types": "tsc --emitDeclarationOnly",
16
- "copy:types": "cp src/types.d.ts dist/index.d.ts",
12
+ "build": "tsc",
17
13
  "lint": "eslint src",
18
- "test": "jest",
19
- "test:unit": "jest --testPathIgnorePatterns=tests/e2e",
20
- "test:e2e": "jest tests/e2e",
21
- "test:watch": "jest --watch",
22
- "test:coverage": "jest --coverage",
14
+ "test": "vitest run",
15
+ "test:unit": "vitest run tests/unit",
16
+ "test:e2e": "vitest run tests/e2e",
17
+ "test:watch": "vitest",
18
+ "test:coverage": "vitest run --coverage",
23
19
  "prepublishOnly": "npm run build"
24
20
  },
25
21
  "dependencies": {
26
22
  "axios": "^1.6.2"
27
23
  },
28
24
  "devDependencies": {
29
- "@babel/core": "^7.23.3",
30
- "@babel/preset-env": "^7.23.3",
31
- "@rollup/plugin-babel": "^6.0.4",
32
- "@rollup/plugin-commonjs": "^25.0.7",
33
- "@rollup/plugin-node-resolve": "^15.2.3",
34
- "@rollup/plugin-terser": "^0.4.4",
35
- "@types/jest": "^29.5.10",
36
- "babel-jest": "^29.7.0",
25
+ "vitest": "^1.0.0",
26
+ "@vitest/ui": "^1.0.0",
27
+ "@vitest/coverage-istanbul": "^1.0.0",
28
+ "@vitest/coverage-v8": "^1.0.0",
37
29
  "dotenv": "^16.3.1",
38
30
  "eslint": "^8.54.0",
39
- "jest": "^29.7.0",
40
31
  "nock": "^13.4.0",
41
- "rollup": "^4.5.2",
42
32
  "typescript": "^5.3.2"
43
33
  },
44
- "peerDependencies": {
45
- "typescript": ">=4.0.0"
46
- },
47
34
  "keywords": [
48
35
  "base44",
49
36
  "api",
@@ -58,5 +45,6 @@
58
45
  "bugs": {
59
46
  "url": "https://github.com/base44/sdk/issues"
60
47
  },
61
- "homepage": "https://github.com/base44/sdk#readme"
48
+ "homepage": "https://github.com/base44/sdk#readme",
49
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
62
50
  }
package/dist/index.esm.js DELETED
@@ -1 +0,0 @@
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://app.base44.com",appId:a,env:i="prod",token:s,requiresAuth:c=!1}=e;console.log("DOES IT?",c,"undefined"!=typeof window);const 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}/integrations/Core/${r}`,a||o,{headers:{"Content-Type":i}}):e.post(`/apps/${t}/integrations/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};
package/dist/index.umd.js DELETED
@@ -1 +0,0 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("axios")):"function"==typeof define&&define.amd?define(["exports","axios"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).base44SDK={},e.axios)}(this,(function(e,t){"use strict";class o 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 n(e){let{baseURL:n,headers:r={},token:a,requiresAuth:i=!1,appId:s,serverUrl:c}=e;const d=t.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 t=e.response?.data?.message||e.response?.data?.detail||e.message,n=new o(t,e.response?.status,e.response?.data?.code,e.response?.data,e);return"production"!==process.env.NODE_ENV&&function(e,t){if(t instanceof o){if(console.error(`${e} ${t.status}: ${t.message}`),t.data)try{console.error("Error data:",JSON.stringify(t.data,null,2))}catch(e){console.error("Error data: [Cannot stringify error data]")}}else console.error(`${e} ${t.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 r(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 a(){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 a=null;if("undefined"!=typeof window&&window.location)try{const e=new URLSearchParams(window.location.search);if(a=e.get(o),a){if(n&&i(a,{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 a}}catch(e){console.error("Error retrieving token from URL:",e)}if("undefined"!=typeof window&&window.localStorage)try{return a=window.localStorage.getItem(t),a}catch(e){console.error("Error retrieving token from localStorage:",e)}return null}function i(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}}e.Base44Error=o,e.createClient=function(e){if(!e||!e.appId)throw new Error("appId is required");const{serverUrl:t="https://app.base44.com",appId:o,env:i="prod",token:s,requiresAuth:c=!1}=e;console.log("DOES IT?",c,"undefined"!=typeof window);const d=n({baseURL:`${t}/api`,headers:{"X-App-Id":String(o),"X-Environment":i},token:s,requiresAuth:c,appId:o,serverUrl:t}),l=r(d,o),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}/integrations/Core/${r}`,a||o,{headers:{"Content-Type":i}}):e.post(`/apps/${t}/integrations/installable/${n}/integration-endpoints/${r}`,a||o,{headers:{"Content-Type":i}})}}})}})}(d,o),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,o,t);if("undefined"!=typeof window){const e=s||a();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:o,env:i,requiresAuth:c})}},e.getAccessToken=a,e.getLoginUrl=function(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}`},e.removeAccessToken=function(){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}},e.saveAccessToken=i}));