@budibase/frontend-core 3.12.13 → 3.12.15
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/package.json +2 -2
- package/src/api/agents.ts +68 -0
- package/src/api/app.ts +16 -2
- package/src/api/auth.ts +17 -1
- package/src/api/index.ts +2 -0
- package/src/api/resource.ts +23 -0
- package/src/api/types.ts +2 -0
- package/src/components/grid/cells/AttachmentCell.svelte +8 -2
- package/src/components/grid/stores/conditions.ts +13 -2
- package/src/utils/index.ts +1 -0
- package/src/utils/login.ts +29 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/frontend-core",
|
|
3
|
-
"version": "3.12.
|
|
3
|
+
"version": "3.12.15",
|
|
4
4
|
"description": "Budibase frontend core libraries used in builder and client",
|
|
5
5
|
"author": "Budibase",
|
|
6
6
|
"license": "MPL-2.0",
|
|
@@ -17,5 +17,5 @@
|
|
|
17
17
|
"shortid": "2.2.15",
|
|
18
18
|
"socket.io-client": "^4.7.5"
|
|
19
19
|
},
|
|
20
|
-
"gitHead": "
|
|
20
|
+
"gitHead": "e773b5a964aab33ff99a5fea0aa40f16dbfaa2ea"
|
|
21
21
|
}
|
package/src/api/agents.ts
CHANGED
|
@@ -6,11 +6,18 @@ import {
|
|
|
6
6
|
ChatAgentResponse,
|
|
7
7
|
CreateToolSourceRequest,
|
|
8
8
|
FetchAgentHistoryResponse,
|
|
9
|
+
LLMStreamChunk,
|
|
9
10
|
} from "@budibase/types"
|
|
11
|
+
|
|
10
12
|
import { BaseAPIClient } from "./types"
|
|
11
13
|
|
|
12
14
|
export interface AgentEndpoints {
|
|
13
15
|
agentChat: (chat: AgentChat) => Promise<ChatAgentResponse>
|
|
16
|
+
agentChatStream: (
|
|
17
|
+
chat: AgentChat,
|
|
18
|
+
onChunk: (chunk: LLMStreamChunk) => void,
|
|
19
|
+
onError?: (error: Error) => void
|
|
20
|
+
) => Promise<void>
|
|
14
21
|
|
|
15
22
|
removeChat: (historyId: string) => Promise<void>
|
|
16
23
|
fetchChats: () => Promise<FetchAgentHistoryResponse>
|
|
@@ -32,6 +39,67 @@ export const buildAgentEndpoints = (API: BaseAPIClient): AgentEndpoints => ({
|
|
|
32
39
|
})
|
|
33
40
|
},
|
|
34
41
|
|
|
42
|
+
agentChatStream: async (chat, onChunk, onError) => {
|
|
43
|
+
const body: ChatAgentRequest = chat
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
// TODO: add support for streaming into the frontend-core API object
|
|
47
|
+
const response = await fetch("/api/agent/chat/stream", {
|
|
48
|
+
method: "POST",
|
|
49
|
+
headers: {
|
|
50
|
+
"Content-Type": "application/json",
|
|
51
|
+
Accept: "application/json",
|
|
52
|
+
},
|
|
53
|
+
body: JSON.stringify(body),
|
|
54
|
+
credentials: "same-origin",
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
throw new Error(`HTTP error! status: ${response.status}`)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const reader = response.body?.getReader()
|
|
62
|
+
if (!reader) {
|
|
63
|
+
throw new Error("Failed to get response reader")
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const decoder = new TextDecoder()
|
|
67
|
+
let buffer = ""
|
|
68
|
+
|
|
69
|
+
while (true) {
|
|
70
|
+
const { done, value } = await reader.read()
|
|
71
|
+
|
|
72
|
+
if (done) break
|
|
73
|
+
|
|
74
|
+
buffer += decoder.decode(value, { stream: true })
|
|
75
|
+
|
|
76
|
+
// Process complete lines
|
|
77
|
+
const lines = buffer.split("\n")
|
|
78
|
+
buffer = lines.pop() || "" // Keep incomplete line in buffer
|
|
79
|
+
|
|
80
|
+
for (const line of lines) {
|
|
81
|
+
if (line.startsWith("data: ")) {
|
|
82
|
+
try {
|
|
83
|
+
const data = line.slice(6) // Remove 'data: ' prefix
|
|
84
|
+
if (data.trim()) {
|
|
85
|
+
const chunk: LLMStreamChunk = JSON.parse(data)
|
|
86
|
+
onChunk(chunk)
|
|
87
|
+
}
|
|
88
|
+
} catch (parseError) {
|
|
89
|
+
console.error("Failed to parse SSE data:", parseError)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
} catch (error: any) {
|
|
95
|
+
if (onError) {
|
|
96
|
+
onError(error)
|
|
97
|
+
} else {
|
|
98
|
+
throw error
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
|
|
35
103
|
removeChat: async (historyId: string) => {
|
|
36
104
|
return await API.delete({
|
|
37
105
|
url: `/api/agent/history/${historyId}`,
|
package/src/api/app.ts
CHANGED
|
@@ -12,9 +12,11 @@ import {
|
|
|
12
12
|
FetchAppPackageResponse,
|
|
13
13
|
FetchAppsResponse,
|
|
14
14
|
FetchDeploymentResponse,
|
|
15
|
+
FetchPublishedAppsResponse,
|
|
15
16
|
GetDiagnosticsResponse,
|
|
16
17
|
ImportToUpdateAppRequest,
|
|
17
18
|
ImportToUpdateAppResponse,
|
|
19
|
+
PublishAppRequest,
|
|
18
20
|
PublishAppResponse,
|
|
19
21
|
RevertAppClientResponse,
|
|
20
22
|
RevertAppResponse,
|
|
@@ -32,7 +34,10 @@ export interface AppEndpoints {
|
|
|
32
34
|
metadata: UpdateAppRequest
|
|
33
35
|
) => Promise<UpdateAppResponse>
|
|
34
36
|
unpublishApp: (appId: string) => Promise<UnpublishAppResponse>
|
|
35
|
-
publishAppChanges: (
|
|
37
|
+
publishAppChanges: (
|
|
38
|
+
appId: string,
|
|
39
|
+
opts?: PublishAppRequest
|
|
40
|
+
) => Promise<PublishAppResponse>
|
|
36
41
|
revertAppChanges: (appId: string) => Promise<RevertAppResponse>
|
|
37
42
|
updateAppClientVersion: (appId: string) => Promise<UpdateAppClientResponse>
|
|
38
43
|
revertAppClientVersion: (appId: string) => Promise<RevertAppClientResponse>
|
|
@@ -55,6 +60,7 @@ export interface AppEndpoints {
|
|
|
55
60
|
appId: string
|
|
56
61
|
) => Promise<FetchAppDefinitionResponse>
|
|
57
62
|
addSampleData: (appId: string) => Promise<AddAppSampleDataResponse>
|
|
63
|
+
getPublishedApps: () => Promise<FetchPublishedAppsResponse["apps"]>
|
|
58
64
|
|
|
59
65
|
// Missing request or response types
|
|
60
66
|
importApps: (apps: any) => Promise<any>
|
|
@@ -86,9 +92,10 @@ export const buildAppEndpoints = (API: BaseAPIClient): AppEndpoints => ({
|
|
|
86
92
|
/**
|
|
87
93
|
* Publishes the current app.
|
|
88
94
|
*/
|
|
89
|
-
publishAppChanges: async appId => {
|
|
95
|
+
publishAppChanges: async (appId, opts) => {
|
|
90
96
|
return await API.post({
|
|
91
97
|
url: `/api/applications/${appId}/publish`,
|
|
98
|
+
body: opts,
|
|
92
99
|
})
|
|
93
100
|
},
|
|
94
101
|
|
|
@@ -267,4 +274,11 @@ export const buildAppEndpoints = (API: BaseAPIClient): AppEndpoints => ({
|
|
|
267
274
|
url: `/api/applications/${appId}/sample`,
|
|
268
275
|
})
|
|
269
276
|
},
|
|
277
|
+
|
|
278
|
+
getPublishedApps: async () => {
|
|
279
|
+
const response = await API.get<FetchPublishedAppsResponse>({
|
|
280
|
+
url: `/api/client/applications`,
|
|
281
|
+
})
|
|
282
|
+
return response.apps
|
|
283
|
+
},
|
|
270
284
|
})
|
package/src/api/auth.ts
CHANGED
|
@@ -12,12 +12,16 @@ import {
|
|
|
12
12
|
} from "@budibase/types"
|
|
13
13
|
import { BaseAPIClient } from "./types"
|
|
14
14
|
|
|
15
|
+
export interface ExtendedLoginResponse extends LoginResponse {
|
|
16
|
+
invalidatedSessionCount?: number
|
|
17
|
+
}
|
|
18
|
+
|
|
15
19
|
export interface AuthEndpoints {
|
|
16
20
|
logIn: (
|
|
17
21
|
tenantId: string,
|
|
18
22
|
username: string,
|
|
19
23
|
password: string
|
|
20
|
-
) => Promise<
|
|
24
|
+
) => Promise<ExtendedLoginResponse>
|
|
21
25
|
logOut: () => Promise<LogoutResponse>
|
|
22
26
|
requestForgotPassword: (
|
|
23
27
|
tenantId: string,
|
|
@@ -46,6 +50,18 @@ export const buildAuthEndpoints = (API: BaseAPIClient): AuthEndpoints => ({
|
|
|
46
50
|
username,
|
|
47
51
|
password,
|
|
48
52
|
},
|
|
53
|
+
parseResponse: async response => {
|
|
54
|
+
const data = (await response.json()) as LoginResponse
|
|
55
|
+
const invalidatedSessionCount = response.headers.get(
|
|
56
|
+
"X-Session-Invalidated-Count"
|
|
57
|
+
)
|
|
58
|
+
return {
|
|
59
|
+
...data,
|
|
60
|
+
invalidatedSessionCount: invalidatedSessionCount
|
|
61
|
+
? parseInt(invalidatedSessionCount)
|
|
62
|
+
: 0,
|
|
63
|
+
} as ExtendedLoginResponse
|
|
64
|
+
},
|
|
49
65
|
})
|
|
50
66
|
},
|
|
51
67
|
|
package/src/api/index.ts
CHANGED
|
@@ -50,6 +50,7 @@ import { buildAgentEndpoints } from "./agents"
|
|
|
50
50
|
import { buildFeatureFlagEndpoints } from "./features"
|
|
51
51
|
import { buildNavigationEndpoints } from "./navigation"
|
|
52
52
|
import { buildWorkspaceAppEndpoints } from "./workspaceApps"
|
|
53
|
+
import { buildResourceEndpoints } from "./resource"
|
|
53
54
|
|
|
54
55
|
export type { APIClient } from "./types"
|
|
55
56
|
|
|
@@ -300,5 +301,6 @@ export const createAPIClient = (config: APIClientConfig = {}): APIClient => {
|
|
|
300
301
|
oauth2: buildOAuth2Endpoints(API),
|
|
301
302
|
navigation: buildNavigationEndpoints(API),
|
|
302
303
|
workspaceApp: buildWorkspaceAppEndpoints(API),
|
|
304
|
+
resource: buildResourceEndpoints(API),
|
|
303
305
|
}
|
|
304
306
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ResourceUsageRequest, ResourceUsageResponse } from "@budibase/types"
|
|
2
|
+
import { BaseAPIClient } from "./types"
|
|
3
|
+
|
|
4
|
+
export interface ResourceEndpoints {
|
|
5
|
+
searchForUsage: (body: {
|
|
6
|
+
automationIds?: string[]
|
|
7
|
+
workspaceAppIds?: string[]
|
|
8
|
+
}) => Promise<ResourceUsageResponse>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const buildResourceEndpoints = (
|
|
12
|
+
API: BaseAPIClient
|
|
13
|
+
): ResourceEndpoints => ({
|
|
14
|
+
searchForUsage: async (body: {
|
|
15
|
+
automationIds?: string[]
|
|
16
|
+
workspaceAppIds?: string[]
|
|
17
|
+
}) => {
|
|
18
|
+
return await API.post<ResourceUsageRequest, ResourceUsageResponse>({
|
|
19
|
+
url: `/api/resources/usage`,
|
|
20
|
+
body,
|
|
21
|
+
})
|
|
22
|
+
},
|
|
23
|
+
})
|
package/src/api/types.ts
CHANGED
|
@@ -37,6 +37,7 @@ import { ViewV2Endpoints } from "./viewsV2"
|
|
|
37
37
|
import { AgentEndpoints } from "./agents"
|
|
38
38
|
import { NavigationEndpoints } from "./navigation"
|
|
39
39
|
import { WorkspaceAppEndpoints } from "./workspaceApps"
|
|
40
|
+
import { ResourceEndpoints } from "./resource"
|
|
40
41
|
|
|
41
42
|
export enum HTTPMethod {
|
|
42
43
|
POST = "POST",
|
|
@@ -140,6 +141,7 @@ export type APIClient = BaseAPIClient &
|
|
|
140
141
|
UserEndpoints &
|
|
141
142
|
FeatureFlagEndpoints &
|
|
142
143
|
ViewEndpoints & {
|
|
144
|
+
resource: ResourceEndpoints
|
|
143
145
|
rowActions: RowActionEndpoints
|
|
144
146
|
viewV2: ViewV2Endpoints
|
|
145
147
|
oauth2: OAuth2Endpoints
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
export let schema
|
|
13
13
|
export let maximum
|
|
14
14
|
|
|
15
|
-
const { API, notifications, props } = getContext("grid")
|
|
15
|
+
const { API, notifications, props, datasource } = getContext("grid")
|
|
16
16
|
const imageExtensions = ["png", "tiff", "gif", "raw", "jpg", "jpeg"]
|
|
17
17
|
|
|
18
18
|
let isOpen = false
|
|
@@ -55,7 +55,13 @@
|
|
|
55
55
|
data.append("file", fileList[i])
|
|
56
56
|
}
|
|
57
57
|
try {
|
|
58
|
-
|
|
58
|
+
const tableId = $datasource?.tableId || $datasource?.id
|
|
59
|
+
if (tableId) {
|
|
60
|
+
return await API.uploadAttachment(tableId, data)
|
|
61
|
+
} else {
|
|
62
|
+
// Fallback to builder endpoint if no table context
|
|
63
|
+
return await API.uploadBuilderAttachment(data)
|
|
64
|
+
}
|
|
59
65
|
} catch (error) {
|
|
60
66
|
$notifications.error(error.message || "Failed to upload attachment")
|
|
61
67
|
return []
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
EmptyFilterOption,
|
|
6
6
|
UIRow,
|
|
7
7
|
UICondition,
|
|
8
|
+
EXTERNAL_ROW_REV,
|
|
8
9
|
} from "@budibase/types"
|
|
9
10
|
import { Store as StoreContext } from "."
|
|
10
11
|
|
|
@@ -72,9 +73,19 @@ export const initialise = (context: StoreContext) => {
|
|
|
72
73
|
const $metadata = get(metadata)
|
|
73
74
|
let metadataUpdates: Record<string, any> = {}
|
|
74
75
|
for (let row of $rows) {
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
const changed =
|
|
77
|
+
// No _rev indicates a new row
|
|
78
|
+
!row._rev ||
|
|
79
|
+
// _rev changed since last evaluation
|
|
80
|
+
$metadata[row._id].version !== row._rev ||
|
|
81
|
+
// this is an external row, we have no way to know if it has changed, so
|
|
82
|
+
// we always re-evaluate
|
|
83
|
+
row._rev === EXTERNAL_ROW_REV
|
|
84
|
+
if (!changed) {
|
|
85
|
+
continue
|
|
77
86
|
}
|
|
87
|
+
|
|
88
|
+
$metadata[row._id] = evaluateConditions(row, $conditions)
|
|
78
89
|
}
|
|
79
90
|
if (Object.keys(metadataUpdates).length) {
|
|
80
91
|
metadata.update(state => ({
|
package/src/utils/index.ts
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MAX_SESSIONS_PER_USER } from "@budibase/shared-core"
|
|
2
|
+
|
|
3
|
+
const SESSIONS_INVALIDATED_KEY = "bb-sessions-invalidated"
|
|
4
|
+
|
|
5
|
+
// export function checkIfSessionsInvalidatedAndNotify() {
|
|
6
|
+
export function popNumSessionsInvalidated() {
|
|
7
|
+
const invalidatedCount = parseInt(
|
|
8
|
+
localStorage.getItem(SESSIONS_INVALIDATED_KEY) || "0",
|
|
9
|
+
10
|
|
10
|
+
)
|
|
11
|
+
localStorage.removeItem(SESSIONS_INVALIDATED_KEY)
|
|
12
|
+
return invalidatedCount
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function pushNumSessionsInvalidated(num: number) {
|
|
16
|
+
const currentCount = parseInt(
|
|
17
|
+
localStorage.getItem(SESSIONS_INVALIDATED_KEY) || "0",
|
|
18
|
+
10
|
|
19
|
+
)
|
|
20
|
+
localStorage.setItem(
|
|
21
|
+
SESSIONS_INVALIDATED_KEY,
|
|
22
|
+
(currentCount + num).toString()
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function invalidationMessage(num: number) {
|
|
27
|
+
const sessionText = num === 1 ? "session" : "sessions"
|
|
28
|
+
return `You've been logged out of ${num} other ${sessionText} because users are only allowed ${MAX_SESSIONS_PER_USER} active sessions at any one time.`
|
|
29
|
+
}
|