@cat-factory/app 0.46.5 → 0.46.6
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.
|
@@ -49,6 +49,13 @@ export function createApiClient(): WretchInstance {
|
|
|
49
49
|
const apiBase = useRuntimeConfig().public.apiBase
|
|
50
50
|
return wretch(apiBase).middlewares([
|
|
51
51
|
(next) => async (url, opts) => {
|
|
52
|
+
// Tag every request with this tab's stable connection id (matched to the `?cid=` on
|
|
53
|
+
// the realtime WebSocket) so the backend can skip echoing a board mutation's coarse
|
|
54
|
+
// event back to the connection that caused it — see `utils/connectionId.ts`.
|
|
55
|
+
opts.headers = {
|
|
56
|
+
...(opts.headers as Record<string, string> | undefined),
|
|
57
|
+
'X-Connection-Id': connectionId(),
|
|
58
|
+
}
|
|
52
59
|
const token = useAuthStore().token
|
|
53
60
|
if (token) {
|
|
54
61
|
opts.headers = {
|
|
@@ -119,7 +119,11 @@ export function useWorkspaceStream() {
|
|
|
119
119
|
// A workspace switch (or stop()) may have happened while awaiting the mint.
|
|
120
120
|
if (stopped || workspace.workspaceId !== workspaceId) return
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
// Carry this tab's stable connection id so the backend can suppress echoing a board
|
|
123
|
+
// mutation's coarse event back to the connection that caused it (same id the api
|
|
124
|
+
// client sends as `X-Connection-Id`) — see `utils/connectionId.ts`.
|
|
125
|
+
const cid = `cid=${encodeURIComponent(connectionId())}`
|
|
126
|
+
const query = ticket ? `?ticket=${encodeURIComponent(ticket)}&${cid}` : `?${cid}`
|
|
123
127
|
socket = new WebSocket(`${wsBase}/workspaces/${workspaceId}/events${query}`)
|
|
124
128
|
|
|
125
129
|
socket.onopen = () => {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A stable per-tab connection id, generated once on first use. It rides on every REST
|
|
3
|
+
* request (the `X-Connection-Id` header, added in the api client) AND on the realtime
|
|
4
|
+
* WebSocket connect (`?cid=`), so the backend can recognise the connection that caused a
|
|
5
|
+
* board mutation and skip echoing the resulting coarse `board` event back to it.
|
|
6
|
+
*
|
|
7
|
+
* Without this, a client consumes the WebSocket event for its OWN move and runs a
|
|
8
|
+
* debounced full board refresh; a snapshot fetched mid-flight (between two rapid drags)
|
|
9
|
+
* carries a stale position, so the block snaps back to where it was after the previous
|
|
10
|
+
* move. Suppressing the self-echo leaves the originating client on its optimistic state +
|
|
11
|
+
* its own REST response (already the freshest), while other clients still refresh.
|
|
12
|
+
*/
|
|
13
|
+
let cached: string | null = null
|
|
14
|
+
|
|
15
|
+
export function connectionId(): string {
|
|
16
|
+
if (cached) return cached
|
|
17
|
+
cached =
|
|
18
|
+
globalThis.crypto?.randomUUID?.() ??
|
|
19
|
+
`cid-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`
|
|
20
|
+
return cached
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.46.
|
|
3
|
+
"version": "0.46.6",
|
|
4
4
|
"description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|