@base44-preview/sdk 0.8.20-pr.139.6d44627 → 0.8.20-pr.141.01e370e
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.
|
@@ -7,6 +7,39 @@
|
|
|
7
7
|
* @internal
|
|
8
8
|
*/
|
|
9
9
|
export function createFunctionsModule(axios, appId) {
|
|
10
|
+
const joinBaseUrl = (base, path) => {
|
|
11
|
+
if (!base)
|
|
12
|
+
return path;
|
|
13
|
+
return `${String(base).replace(/\/$/, "")}${path}`;
|
|
14
|
+
};
|
|
15
|
+
const isBodyInit = (value) => value instanceof FormData ||
|
|
16
|
+
value instanceof Blob ||
|
|
17
|
+
value instanceof URLSearchParams ||
|
|
18
|
+
value instanceof ReadableStream ||
|
|
19
|
+
value instanceof ArrayBuffer ||
|
|
20
|
+
ArrayBuffer.isView(value);
|
|
21
|
+
const toHeaders = (inputHeaders) => {
|
|
22
|
+
var _a, _b;
|
|
23
|
+
const headers = new Headers();
|
|
24
|
+
const appendHeaders = (source) => {
|
|
25
|
+
if (!source)
|
|
26
|
+
return;
|
|
27
|
+
Object.entries(source).forEach(([key, value]) => {
|
|
28
|
+
if (value !== undefined && value !== null) {
|
|
29
|
+
headers.set(key, String(value));
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
// Axios keeps defaults in method-specific buckets.
|
|
34
|
+
appendHeaders((_a = axios.defaults.headers) === null || _a === void 0 ? void 0 : _a.common);
|
|
35
|
+
appendHeaders((_b = axios.defaults.headers) === null || _b === void 0 ? void 0 : _b.post);
|
|
36
|
+
if (inputHeaders) {
|
|
37
|
+
new Headers(inputHeaders).forEach((value, key) => {
|
|
38
|
+
headers.set(key, value);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return headers;
|
|
42
|
+
};
|
|
10
43
|
return {
|
|
11
44
|
// Invoke a custom backend function by name
|
|
12
45
|
async invoke(functionName, data) {
|
|
@@ -39,5 +72,42 @@ export function createFunctionsModule(axios, appId) {
|
|
|
39
72
|
}
|
|
40
73
|
return axios.post(`/apps/${appId}/functions/${functionName}`, formData || data, { headers: { "Content-Type": contentType } });
|
|
41
74
|
},
|
|
75
|
+
// Fetch a backend function endpoint directly (supports streaming).
|
|
76
|
+
async fetch(path, init = {}) {
|
|
77
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
78
|
+
const primaryPath = `/functions${normalizedPath}`;
|
|
79
|
+
const fallbackPath = `/apps/${appId}/functions${normalizedPath}`;
|
|
80
|
+
const { data, ...fetchInit } = init;
|
|
81
|
+
const headers = toHeaders(fetchInit.headers);
|
|
82
|
+
if (!headers.has("X-App-Id")) {
|
|
83
|
+
headers.set("X-App-Id", appId);
|
|
84
|
+
}
|
|
85
|
+
let body = fetchInit.body;
|
|
86
|
+
if (body === undefined && data !== undefined) {
|
|
87
|
+
if (data === null) {
|
|
88
|
+
body = null;
|
|
89
|
+
}
|
|
90
|
+
else if (typeof data === "string" ||
|
|
91
|
+
isBodyInit(data)) {
|
|
92
|
+
body = data;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
body = JSON.stringify(data);
|
|
96
|
+
if (!headers.has("Content-Type")) {
|
|
97
|
+
headers.set("Content-Type", "application/json");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const requestInit = {
|
|
102
|
+
...fetchInit,
|
|
103
|
+
headers,
|
|
104
|
+
body,
|
|
105
|
+
};
|
|
106
|
+
let response = await fetch(joinBaseUrl(axios.defaults.baseURL, primaryPath), requestInit);
|
|
107
|
+
if (response.status === 404) {
|
|
108
|
+
response = await fetch(joinBaseUrl(axios.defaults.baseURL, fallbackPath), requestInit);
|
|
109
|
+
}
|
|
110
|
+
return response;
|
|
111
|
+
},
|
|
42
112
|
};
|
|
43
113
|
}
|
|
@@ -14,6 +14,16 @@ export interface FunctionNameRegistry {
|
|
|
14
14
|
* ```
|
|
15
15
|
*/
|
|
16
16
|
export type FunctionName = keyof FunctionNameRegistry extends never ? string : keyof FunctionNameRegistry;
|
|
17
|
+
/**
|
|
18
|
+
* Options for {@linkcode FunctionsModule.fetch}.
|
|
19
|
+
*
|
|
20
|
+
* Extends native `fetch` options with a `data` convenience property that
|
|
21
|
+
* is JSON-stringified when `body` is not provided.
|
|
22
|
+
*/
|
|
23
|
+
export type FunctionsFetchInit = RequestInit & {
|
|
24
|
+
/** Convenience payload for JSON requests when `body` is omitted. */
|
|
25
|
+
data?: unknown;
|
|
26
|
+
};
|
|
17
27
|
/**
|
|
18
28
|
* Functions module for invoking custom backend functions.
|
|
19
29
|
*
|
|
@@ -68,4 +78,18 @@ export interface FunctionsModule {
|
|
|
68
78
|
* ```
|
|
69
79
|
*/
|
|
70
80
|
invoke(functionName: FunctionName, data?: Record<string, any>): Promise<any>;
|
|
81
|
+
/**
|
|
82
|
+
* Performs a direct HTTP request to a backend function path and returns the native `Response`.
|
|
83
|
+
*
|
|
84
|
+
* Use this when you need streaming behavior (SSE, chunked text, NDJSON),
|
|
85
|
+
* because `invoke()` buffers the full response.
|
|
86
|
+
*
|
|
87
|
+
* Requests are sent to `/api/functions/<path>`, with automatic fallback to
|
|
88
|
+
* `/api/apps/<appId>/functions/<path>` on `404` for compatibility.
|
|
89
|
+
*
|
|
90
|
+
* @param path - Function path, e.g. `/streaming_demo` or `/streaming_demo/deep/path`
|
|
91
|
+
* @param init - Native fetch options, plus optional `data` for JSON payloads.
|
|
92
|
+
* @returns Promise resolving to a native fetch `Response`
|
|
93
|
+
*/
|
|
94
|
+
fetch(path: string, init?: FunctionsFetchInit): Promise<Response>;
|
|
71
95
|
}
|