Skip to content

Commit 3f8ded5

Browse files
committed
feat: add backend function versioning support
- Add extractSnapshotIdFromHost utility to detect environment from URL - Include Base44-Functions-Version header in function calls - Support functionsVersion parameter in client configuration - Automatically route function calls to correct deployment based on URL pattern This ensures backend functions work correctly with app versioning, calling the right deployment for production, preview, and checkpoint environments.
1 parent e78162e commit 3f8ded5

3 files changed

Lines changed: 61 additions & 13 deletions

File tree

src/client.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,29 @@ export function createClient(config: {
2222
token?: string;
2323
serviceToken?: string;
2424
requiresAuth?: boolean;
25+
functionsVersion?: string;
2526
}) {
2627
const {
2728
serverUrl = "https://base44.app",
2829
appId,
2930
token,
3031
serviceToken,
3132
requiresAuth = false,
33+
functionsVersion
3234
} = config;
3335

36+
const headers = {
37+
"X-App-Id": String(appId),
38+
}
39+
40+
const functionHeaders = functionsVersion ? {
41+
...headers,
42+
"Base44-Functions-Version": functionsVersion
43+
} : headers;
44+
3445
const axiosClient = createAxiosClient({
3546
baseURL: `${serverUrl}/api`,
36-
headers: {
37-
"X-App-Id": String(appId),
38-
},
47+
headers,
3948
token,
4049
requiresAuth,
4150
appId,
@@ -44,9 +53,7 @@ export function createClient(config: {
4453

4554
const functionsAxiosClient = createAxiosClient({
4655
baseURL: `${serverUrl}/api`,
47-
headers: {
48-
"X-App-Id": String(appId),
49-
},
56+
headers: functionHeaders,
5057
token,
5158
requiresAuth,
5259
appId,
@@ -56,19 +63,15 @@ export function createClient(config: {
5663

5764
const serviceRoleAxiosClient = createAxiosClient({
5865
baseURL: `${serverUrl}/api`,
59-
headers: {
60-
"X-App-Id": String(appId),
61-
},
66+
headers,
6267
token: serviceToken,
6368
serverUrl,
6469
appId,
6570
});
6671

6772
const serviceRoleFunctionsAxiosClient = createAxiosClient({
6873
baseURL: `${serverUrl}/api`,
69-
headers: {
70-
"X-App-Id": String(appId),
71-
},
74+
headers: functionHeaders,
7275
token: serviceToken,
7376
serverUrl,
7477
appId,
@@ -160,6 +163,7 @@ export function createClientFromRequest(request: Request) {
160163
);
161164
const appId = request.headers.get("Base44-App-Id");
162165
const serverUrlHeader = request.headers.get("Base44-Api-Url");
166+
const functionsVersion = request.headers.get("Base44-Functions-Version");
163167

164168
if (!appId) {
165169
throw new Error(
@@ -190,5 +194,6 @@ export function createClientFromRequest(request: Request) {
190194
appId,
191195
token: userToken,
192196
serviceToken: serviceRoleToken,
197+
functionsVersion: functionsVersion ?? undefined
193198
});
194199
}

src/modules/functions.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { AxiosInstance } from "axios";
2+
import { extractSnapshotIdFromHost } from "../utils/extract-snapshot-id-from-host.js";
23

34
/**
45
* Creates the functions module for the Base44 SDK
@@ -41,10 +42,18 @@ export function createFunctionsModule(axios: AxiosInstance, appId: string) {
4142
contentType = "application/json";
4243
}
4344

45+
// Extract functions version from the current URL host
46+
const functionsVersion = extractSnapshotIdFromHost();
47+
4448
return axios.post(
4549
`/apps/${appId}/functions/${functionName}`,
4650
formData || data,
47-
{ headers: { "Content-Type": contentType } }
51+
{
52+
headers: {
53+
"Content-Type": contentType,
54+
"X-Functions-Version": functionsVersion
55+
}
56+
}
4857
);
4958
},
5059
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Extracts the snapshot ID or environment type from the current hostname
3+
* Used to determine which backend function deployment to call
4+
*
5+
* @returns {string} The snapshot ID for checkpoints, 'preview' for preview URLs, or 'prod' for production
6+
*/
7+
export function extractSnapshotIdFromHost(): string {
8+
if (typeof window === "undefined") {
9+
return "prod";
10+
}
11+
12+
const hostname = window.location.hostname;
13+
14+
// Check if it's a checkpoint URL
15+
if (hostname.startsWith("checkpoint--")) {
16+
// Format: checkpoint--{app_id}--{snapshot_id}.domain
17+
const parts = hostname.split("--");
18+
if (parts.length >= 3) {
19+
// Extract snapshot_id (last part before the domain)
20+
const snapshotPart = parts[2];
21+
// Remove domain extension if present
22+
const snapshotId = snapshotPart.split(".")[0];
23+
return snapshotId;
24+
}
25+
}
26+
27+
// Check if it's a preview URL
28+
if (hostname.startsWith("preview--")) {
29+
return "preview";
30+
}
31+
32+
// Production URLs - return "prod"
33+
return "prod";
34+
}

0 commit comments

Comments
 (0)