@base44-preview/sdk 0.0.0-preview

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,51 @@
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
+ getSsoAccessToken(): Promise<import("axios").AxiosResponse<any, any>>;
23
+ updateMe(data: Record<string, any>): Promise<import("axios").AxiosResponse<any, any>>;
24
+ redirectToLogin(nextUrl: string): void;
25
+ logout(redirectUrl?: string): void;
26
+ setToken(token: string, saveToStorage?: boolean): void;
27
+ loginViaUsernamePassword(email: string, password: string, turnstileToken?: string): Promise<{
28
+ access_token: string;
29
+ user: any;
30
+ }>;
31
+ isAuthenticated(): Promise<boolean>;
32
+ };
33
+ functions: {
34
+ invoke(functionName: string, data: Record<string, any>): Promise<import("axios").AxiosResponse<any, any>>;
35
+ };
36
+ /**
37
+ * Set authentication token for all requests
38
+ * @param {string} newToken - New auth token
39
+ */
40
+ setToken(newToken: string): void;
41
+ /**
42
+ * Get current configuration
43
+ * @returns {Object} Current configuration
44
+ */
45
+ getConfig(): {
46
+ serverUrl: string;
47
+ appId: string;
48
+ env: string;
49
+ requiresAuth: boolean;
50
+ };
51
+ };
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.redirectToLogin(window.location.href);
64
+ }
65
+ }
66
+ catch (error) {
67
+ console.error("Authentication check failed:", error);
68
+ auth.redirectToLogin(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
+ }
@@ -0,0 +1,4 @@
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 ADDED
@@ -0,0 +1,6 @@
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,61 @@
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
+ * Get current user sso access token
17
+ * @returns {Promise<Object>} Current user sso access_token
18
+ */
19
+ getSsoAccessToken(): Promise<import("axios").AxiosResponse<any, any>>;
20
+ /**
21
+ * Update current user data
22
+ * @param {Object} data - Updated user data
23
+ * @returns {Promise<Object>} Updated user
24
+ */
25
+ updateMe(data: Record<string, any>): Promise<import("axios").AxiosResponse<any, any>>;
26
+ /**
27
+ * Redirects the user to the app's login page
28
+ * @param {string} nextUrl - URL to redirect to after successful login
29
+ * @throws {Error} When not in a browser environment
30
+ */
31
+ redirectToLogin(nextUrl: string): void;
32
+ /**
33
+ * Logout the current user
34
+ * Removes the token from localStorage and optionally redirects to a URL or reloads the page
35
+ * @param redirectUrl - Optional URL to redirect to after logout. Reloads the page if not provided
36
+ * @returns {Promise<void>}
37
+ */
38
+ logout(redirectUrl?: string): void;
39
+ /**
40
+ * Set authentication token
41
+ * @param {string} token - Auth token
42
+ * @param {boolean} [saveToStorage=true] - Whether to save the token to localStorage
43
+ */
44
+ setToken(token: string, saveToStorage?: boolean): void;
45
+ /**
46
+ * Login via username and password
47
+ * @param email - User email
48
+ * @param password - User password
49
+ * @param turnstileToken - Optional Turnstile captcha token
50
+ * @returns Login response with access_token and user
51
+ */
52
+ loginViaUsernamePassword(email: string, password: string, turnstileToken?: string): Promise<{
53
+ access_token: string;
54
+ user: any;
55
+ }>;
56
+ /**
57
+ * Verify if the current token is valid
58
+ * @returns {Promise<boolean>} True if token is valid
59
+ */
60
+ isAuthenticated(): Promise<boolean>;
61
+ };
@@ -0,0 +1,144 @@
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
+ * Get current user sso access token
19
+ * @returns {Promise<Object>} Current user sso access_token
20
+ */
21
+ async getSsoAccessToken() {
22
+ return axios.get(`/apps/${appId}/auth/sso/accesstoken`);
23
+ },
24
+ /**
25
+ * Update current user data
26
+ * @param {Object} data - Updated user data
27
+ * @returns {Promise<Object>} Updated user
28
+ */
29
+ async updateMe(data) {
30
+ return axios.put(`/apps/${appId}/entities/User/me`, data);
31
+ },
32
+ /**
33
+ * Redirects the user to the app's login page
34
+ * @param {string} nextUrl - URL to redirect to after successful login
35
+ * @throws {Error} When not in a browser environment
36
+ */
37
+ redirectToLogin(nextUrl) {
38
+ // This function only works in a browser environment
39
+ if (typeof window === "undefined") {
40
+ throw new Error("Login method can only be used in a browser environment");
41
+ }
42
+ // If nextUrl is not provided, use the current URL
43
+ const redirectUrl = nextUrl || window.location.href;
44
+ // Build the login URL
45
+ const loginUrl = `/login?from_url=${encodeURIComponent(redirectUrl)}`;
46
+ // Redirect to the login page
47
+ window.location.href = loginUrl;
48
+ },
49
+ /**
50
+ * Logout the current user
51
+ * Removes the token from localStorage and optionally redirects to a URL or reloads the page
52
+ * @param redirectUrl - Optional URL to redirect to after logout. Reloads the page if not provided
53
+ * @returns {Promise<void>}
54
+ */
55
+ logout(redirectUrl) {
56
+ // Remove token from axios headers
57
+ delete axios.defaults.headers.common["Authorization"];
58
+ // Remove token from localStorage
59
+ if (typeof window !== "undefined" && window.localStorage) {
60
+ try {
61
+ window.localStorage.removeItem("base44_access_token");
62
+ }
63
+ catch (e) {
64
+ console.error("Failed to remove token from localStorage:", e);
65
+ }
66
+ }
67
+ // Redirect if a URL is provided
68
+ if (typeof window !== "undefined") {
69
+ if (redirectUrl) {
70
+ window.location.href = redirectUrl;
71
+ }
72
+ else {
73
+ window.location.reload();
74
+ }
75
+ }
76
+ },
77
+ /**
78
+ * Set authentication token
79
+ * @param {string} token - Auth token
80
+ * @param {boolean} [saveToStorage=true] - Whether to save the token to localStorage
81
+ */
82
+ setToken(token, saveToStorage = true) {
83
+ if (!token)
84
+ return;
85
+ axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
86
+ // Save token to localStorage if requested
87
+ if (saveToStorage &&
88
+ typeof window !== "undefined" &&
89
+ window.localStorage) {
90
+ try {
91
+ window.localStorage.setItem("base44_access_token", token);
92
+ }
93
+ catch (e) {
94
+ console.error("Failed to save token to localStorage:", e);
95
+ }
96
+ }
97
+ },
98
+ /**
99
+ * Login via username and password
100
+ * @param email - User email
101
+ * @param password - User password
102
+ * @param turnstileToken - Optional Turnstile captcha token
103
+ * @returns Login response with access_token and user
104
+ */
105
+ async loginViaUsernamePassword(email, password, turnstileToken) {
106
+ var _a;
107
+ try {
108
+ const response = await axios.post(`/apps/${appId}/auth/login`, {
109
+ email,
110
+ password,
111
+ ...(turnstileToken && { turnstile_token: turnstileToken }),
112
+ });
113
+ const { access_token, user } = response;
114
+ if (access_token) {
115
+ this.setToken(access_token);
116
+ }
117
+ return {
118
+ access_token,
119
+ user,
120
+ };
121
+ }
122
+ catch (error) {
123
+ // Handle authentication errors and cleanup
124
+ if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 401) {
125
+ await this.logout();
126
+ }
127
+ throw error;
128
+ }
129
+ },
130
+ /**
131
+ * Verify if the current token is valid
132
+ * @returns {Promise<boolean>} True if token is valid
133
+ */
134
+ async isAuthenticated() {
135
+ try {
136
+ await this.me();
137
+ return true;
138
+ }
139
+ catch (error) {
140
+ return false;
141
+ }
142
+ },
143
+ };
144
+ }
@@ -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 ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@base44-preview/sdk",
3
+ "version": "0.0.0-preview",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "type": "module",
7
+ "files": [
8
+ "dist",
9
+ "!README.md"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "lint": "eslint src",
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",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "dependencies": {
22
+ "axios": "^1.6.2"
23
+ },
24
+ "devDependencies": {
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",
29
+ "dotenv": "^16.3.1",
30
+ "eslint": "^8.54.0",
31
+ "nock": "^13.4.0",
32
+ "typescript": "^5.3.2"
33
+ },
34
+ "keywords": [
35
+ "api",
36
+ "sdk"
37
+ ],
38
+ "license": "MIT"
39
+ }