-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathaxios-client.ts
More file actions
169 lines (154 loc) · 4.5 KB
/
Copy pathaxios-client.ts
File metadata and controls
169 lines (154 loc) · 4.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import axios from "axios";
export class Base44Error extends Error {
status: number;
code: string;
data: any;
originalError: unknown;
constructor(
message: string,
status: number,
code: string,
data: any,
originalError: unknown
) {
super(message);
this.name = "Base44Error";
this.status = status;
this.code = code;
this.data = data;
this.originalError = originalError;
}
// Add a method to safely serialize this error without circular references
toJSON() {
return {
name: this.name,
message: this.message,
status: this.status,
code: this.code,
data: this.data,
};
}
}
/**
* Safely logs error information without circular references
* @param {string} prefix - Prefix for the log message
* @param {Error} error - The error to log
*/
function safeErrorLog(prefix: string, error: unknown) {
if (error instanceof Base44Error) {
console.error(`${prefix} ${error.status}: ${error.message}`);
if (error.data) {
try {
console.error("Error data:", JSON.stringify(error.data, null, 2));
} catch (e) {
console.error("Error data: [Cannot stringify error data]");
}
}
} else {
console.error(
`${prefix} ${error instanceof Error ? error.message : String(error)}`
);
}
}
/**
* Redirects to the login page with the current URL as return destination
* @param {string} serverUrl - Base server URL
* @param {string|number} appId - Application ID
*/
function redirectToLogin(serverUrl: string, appId: string) {
if (typeof window === "undefined") {
return; // Can't redirect in non-browser environment
}
const currentUrl = encodeURIComponent(window.location.href);
const loginUrl = `${serverUrl}/login?from_url=${currentUrl}&app_id=${appId}`;
window.location.href = loginUrl;
}
/**
* Creates an axios client with default configuration and interceptors
* @param {Object} options - Client configuration options
* @param {string} options.baseURL - Base URL for all requests
* @param {Object} options.headers - Additional headers
* @param {string} options.token - Auth token
* @param {string} options.apiKey - API key
* @param {boolean} options.requiresAuth - Whether the application requires authentication
* @param {string|number} options.appId - Application ID (needed for login redirect)
* @param {string} options.serverUrl - Server URL (needed for login redirect)
* @returns {import('axios').AxiosInstance} Configured axios instance
*/
export function createAxiosClient({
baseURL,
headers = {},
token,
apiKey,
requiresAuth = false,
appId,
serverUrl,
interceptResponses = true,
}: {
baseURL: string;
headers?: Record<string, string>;
token?: string;
apiKey?: string;
requiresAuth?: boolean;
appId: string;
serverUrl: string;
interceptResponses?: boolean;
}) {
const client = axios.create({
baseURL,
headers: {
"Content-Type": "application/json",
Accept: "application/json",
...headers,
},
});
// Add authentication headers
if (token) {
client.defaults.headers.common["Authorization"] = `Bearer ${token}`;
} else if (apiKey) {
client.defaults.headers.common["api_key"] = apiKey;
}
// Add origin URL in browser environment
client.interceptors.request.use((config) => {
if (typeof window !== "undefined") {
config.headers.set("X-Origin-URL", window.location.href);
}
return config;
});
// Handle responses
if (interceptResponses) {
client.interceptors.response.use(
(response) => response.data,
(error) => {
const message =
error.response?.data?.message ||
error.response?.data?.detail ||
error.message;
const base44Error = new Base44Error(
message,
error.response?.status,
error.response?.data?.code,
error.response?.data,
error
);
// Log errors in development
if (process.env.NODE_ENV !== "production") {
safeErrorLog("[Base44 SDK Error]", base44Error);
}
// Check for 403 Forbidden (authentication required) and redirect to login if requiresAuth is true
if (
requiresAuth &&
error.response?.status === 403 &&
typeof window !== "undefined"
) {
// Use a slight delay to allow the error to propagate first
setTimeout(() => {
redirectToLogin(serverUrl, appId);
}, 100);
}
return Promise.reject(base44Error);
}
);
}
return client;
}