camox 0.58.1 → 0.60.2
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/dist/core/createBlock.js +1 -1
- package/dist/core/editing/createEditableBlock.js +2 -2
- package/dist/core/lib/recordScope.js +1 -1
- package/dist/features/canvas/CamoxCanvas.js +2 -2
- package/dist/features/canvas/CanvasOverlays.js +1 -1
- package/dist/features/canvas/sidebar/LayoutPageSeo.js +1 -1
- package/dist/features/canvas/sidebar/PageInspector.js +1 -1
- package/dist/features/content/CamoxContent.js +1 -1
- package/dist/features/content/components/MissingFromLocale.js +1 -1
- package/dist/features/page/CuratedPageContent.js +1 -1
- package/dist/features/preview/CamoxPreview.js +3 -3
- package/dist/features/preview/components/AddBlockSheet.js +1 -1
- package/dist/features/preview/components/AssetLightbox.js +1 -1
- package/dist/features/preview/components/BlockActionsPopover.js +1 -1
- package/dist/features/preview/components/CreatePageModal.js +2 -2
- package/dist/features/preview/components/FieldOverlayStyles.js +1 -1
- package/dist/features/preview/components/MobilePreviewDrawer.js +1 -1
- package/dist/features/preview/components/Overlays.js +1 -1
- package/dist/features/preview/components/PageInfo.js +1 -1
- package/dist/features/preview/components/PagePicker.js +1 -1
- package/dist/features/preview/components/PageTree.js +1 -1
- package/dist/features/preview/components/PreviewPanel.js +1 -1
- package/dist/features/preview/components/PreviewToolbar.js +1 -1
- package/dist/features/preview/components/SelectionEditor.js +2 -2
- package/dist/features/preview/components/StudioEditingFallback.js +1 -1
- package/dist/features/provider/AuthenticatedCamoxProvider.js +1 -1
- package/dist/features/provider/CamoxProvider.js +1 -1
- package/dist/features/provider/CoreCamoxProvider.js +3 -3
- package/dist/features/provider/components/CommandPalette.js +1 -1
- package/dist/features/renderer/RendererApp.js +187 -103
- package/dist/features/renderer/rendererHost.js +3 -7
- package/dist/features/routes/pageRuntime.d.ts +2 -5
- package/dist/features/routes/pageRuntime.js +1 -2
- package/dist/features/runtime/RuntimeChrome.js +1 -1
- package/dist/features/runtime/loopbackFetch.d.ts +8 -0
- package/dist/features/runtime/navigationTarget.js +1 -2
- package/dist/features/runtime/pageApp.js +1 -1
- package/dist/features/runtime/publicCache.d.ts +21 -0
- package/dist/features/runtime/publishingDraft.d.ts +4 -0
- package/dist/features/runtime/rendererClient.js +1 -1
- package/dist/features/runtime/runtime.d.ts +0 -5
- package/dist/features/runtime/runtime.js +80 -33
- package/dist/features/runtime/worker.js +4 -7
- package/dist/features/runtime/workerRequest.d.ts +8 -0
- package/dist/features/runtime/workerRuntime.d.ts +5 -0
- package/dist/features/runtime/workerRuntime.js +6 -0
- package/dist/features/sdkBundle/buildSdkBundle.d.ts +40 -0
- package/dist/features/sdkBundle/buildSdkBundle.js +323 -0
- package/dist/features/sdkBundle/localSdkBundle.d.ts +44 -0
- package/dist/features/sdkBundle/localSdkBundle.js +162 -0
- package/dist/features/sdkBundle/sdkBundle.d.ts +3 -0
- package/dist/features/sdkBundle/sdkBundle.js +4 -0
- package/dist/features/sdkBundle/sdkBundleName.d.ts +59 -0
- package/dist/features/sdkBundle/sdkBundleName.js +164 -0
- package/dist/features/sdkBundle/specifiers.d.ts +34 -0
- package/dist/features/sdkBundle/specifiers.js +146 -0
- package/dist/features/settings/FaviconSettings.js +1 -1
- package/dist/features/settings/SocialProfilesSettings.js +284 -151
- package/dist/features/studio/CamoxStudio.js +1 -1
- package/dist/features/studio/FollowAgentProvider.js +72 -13
- package/dist/features/studio/components/ChatWidget.js +86 -44
- package/dist/features/studio/components/DraftsControl.js +232 -201
- package/dist/features/studio/components/LocalePicker.js +2 -2
- package/dist/features/studio/components/Navbar.js +3 -3
- package/dist/features/studio/components/Patrol.js +312 -209
- package/dist/features/studio/components/ProjectMenu.js +2 -2
- package/dist/features/studio/components/ReviewDraftSheet.js +9 -15
- package/dist/features/studio/components/Squareling.js +164 -66
- package/dist/features/studio/components/ThreadComposer.js +139 -69
- package/dist/features/studio/components/ThreadMessages.js +216 -64
- package/dist/features/studio/components/UserButton.js +2 -2
- package/dist/features/studio/draftLabel.js +1 -2
- package/dist/features/studio/draftNotice.js +0 -1
- package/dist/features/studio/editorWhereContext.js +11 -0
- package/dist/features/studio/showInCanvas.js +1 -1
- package/dist/features/studio/useEditorSelection.js +135 -0
- package/dist/features/vite/definitionsSync.js +14 -60
- package/dist/features/vite/devSignIn.js +1 -1
- package/dist/features/vite/hostedChecks.js +1 -1
- package/dist/features/vite/runtimeDev.js +2 -2
- package/dist/features/vite/sdkBundleBuild.js +74 -0
- package/dist/features/vite/staticAssetHeaders.js +7 -4
- package/dist/features/vite/vite.d.ts +8 -7
- package/dist/features/vite/vite.js +67 -28
- package/dist/lib/api-client-server.js +25 -8
- package/dist/lib/api-client.js +2 -6
- package/dist/lib/auth.js +25 -59
- package/dist/lib/draft-scope.js +5 -25
- package/dist/lib/preview-handoff.js +1 -1
- package/dist/lib/server-auth-cookie.js +23 -11
- package/dist/lib/stored-auth-cookies.js +76 -0
- package/dist/lib/studio-reads.js +1 -1
- package/dist/lib/use-thread.js +40 -40
- package/dist/package.js +1 -1
- package/dist/studio.css +1 -1
- package/package.json +17 -4
- package/skills/camox/references/block-definitions.md +1 -1
- package/dist/features/vite/publishSeededContent.js +0 -30
- package/skills/camox-cli/SKILL.md +0 -15
- package/skills/camox-cli/references/cli-common.md +0 -58
- package/skills/camox-cli/references/cli-content.md +0 -181
- package/skills/camox-cli/references/cli-publishing.md +0 -26
package/dist/lib/auth.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { actionsStore } from "../features/provider/actionsStore.js";
|
|
2
2
|
import { validatePreviewTarget } from "./preview-handoff.js";
|
|
3
|
-
import {
|
|
3
|
+
import { buildClearServerAuthCookieHeader, buildServerAuthCookieHeader, getServerAuthCookieHeader, readServerAuthCookie } from "./server-auth-cookie.js";
|
|
4
|
+
import { getCookie, getSetCookie, parseSetCookieHeader, withCookieHeader } from "./stored-auth-cookies.js";
|
|
4
5
|
import { c } from "react/compiler-runtime";
|
|
5
6
|
import * as React from "react";
|
|
6
7
|
import { oneTimeTokenClient, organizationClient } from "better-auth/client/plugins";
|
|
@@ -9,60 +10,26 @@ import { createAuthClient } from "better-auth/react";
|
|
|
9
10
|
//#region src/lib/auth.ts
|
|
10
11
|
function writeServerAuthCookie(cookie) {
|
|
11
12
|
if (typeof document === "undefined") return;
|
|
12
|
-
const secure = window.location.protocol === "https:"
|
|
13
|
+
const secure = window.location.protocol === "https:";
|
|
13
14
|
if (!cookie) {
|
|
14
|
-
document.cookie = `${buildClearServerAuthCookieHeader()}${secure}`;
|
|
15
|
+
document.cookie = `${buildClearServerAuthCookieHeader()}${secure ? "; Secure" : ""}`;
|
|
15
16
|
return;
|
|
16
17
|
}
|
|
17
|
-
document.cookie =
|
|
18
|
+
document.cookie = buildServerAuthCookieHeader(cookie, { secure });
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return
|
|
32
|
-
}
|
|
33
|
-
function getSetCookie(header, prevCookie) {
|
|
34
|
-
const parsed = parseSetCookieHeader(header);
|
|
35
|
-
let toSetCookie = {};
|
|
36
|
-
parsed.forEach((cookie, key) => {
|
|
37
|
-
const expiresAt = cookie["expires"];
|
|
38
|
-
const maxAge = cookie["max-age"];
|
|
39
|
-
let expires = null;
|
|
40
|
-
if (expiresAt) expires = new Date(String(expiresAt));
|
|
41
|
-
else if (maxAge) expires = new Date(Date.now() + Number(maxAge) * 1e3);
|
|
42
|
-
toSetCookie[key] = {
|
|
43
|
-
value: cookie["value"],
|
|
44
|
-
expires: expires ? expires.toISOString() : null
|
|
45
|
-
};
|
|
46
|
-
});
|
|
47
|
-
if (prevCookie) try {
|
|
48
|
-
toSetCookie = {
|
|
49
|
-
...JSON.parse(prevCookie),
|
|
50
|
-
...toSetCookie
|
|
51
|
-
};
|
|
52
|
-
} catch {}
|
|
53
|
-
return JSON.stringify(toSetCookie);
|
|
54
|
-
}
|
|
55
|
-
function getCookie(cookie) {
|
|
56
|
-
let parsed = {};
|
|
57
|
-
try {
|
|
58
|
-
parsed = JSON.parse(cookie);
|
|
59
|
-
} catch {}
|
|
60
|
-
const parts = [];
|
|
61
|
-
for (const [key, value] of Object.entries(parsed)) {
|
|
62
|
-
if (value.expires && new Date(value.expires) < /* @__PURE__ */ new Date()) continue;
|
|
63
|
-
parts.push(`${key}=${value.value}`);
|
|
64
|
-
}
|
|
65
|
-
return parts.join("; ");
|
|
20
|
+
const STORED_COOKIES_KEY = "better-auth_cookie";
|
|
21
|
+
/**
|
|
22
|
+
* The stored cookies, with the session the website's Worker signed in with added: it exchanges a
|
|
23
|
+
* sign-in's one-time token itself and sets only the mirror. Read storage through this alone,
|
|
24
|
+
* since reading it writes the mirror back from storage.
|
|
25
|
+
*/
|
|
26
|
+
function readStoredCookies(storage, key = STORED_COOKIES_KEY) {
|
|
27
|
+
const stored = storage.getItem(key) || "{}";
|
|
28
|
+
if (typeof document === "undefined") return stored;
|
|
29
|
+
const adopted = withCookieHeader(stored, readServerAuthCookie(document.cookie));
|
|
30
|
+
if (!adopted) return stored;
|
|
31
|
+
storage.setItem(key, adopted);
|
|
32
|
+
return adopted;
|
|
66
33
|
}
|
|
67
34
|
/**
|
|
68
35
|
* Read the cross-domain auth cookie from localStorage and return it as a
|
|
@@ -70,7 +37,7 @@ function getCookie(cookie) {
|
|
|
70
37
|
*/
|
|
71
38
|
function getAuthCookieHeader() {
|
|
72
39
|
if (typeof window === "undefined") return "";
|
|
73
|
-
const cookie = getCookie(localStorage
|
|
40
|
+
const cookie = getCookie(readStoredCookies(localStorage));
|
|
74
41
|
writeServerAuthCookie(cookie);
|
|
75
42
|
return cookie;
|
|
76
43
|
}
|
|
@@ -87,10 +54,7 @@ function crossDomainClient(opts = {}) {
|
|
|
87
54
|
getActions(_, $store) {
|
|
88
55
|
store = $store;
|
|
89
56
|
return {
|
|
90
|
-
getCookie: () =>
|
|
91
|
-
const cookie = storage?.getItem(cookieName);
|
|
92
|
-
return getCookie(cookie || "{}");
|
|
93
|
-
},
|
|
57
|
+
getCookie: () => storage ? getCookie(readStoredCookies(storage, cookieName)) : "",
|
|
94
58
|
updateSession: () => {
|
|
95
59
|
$store.notify("$sessionSignal");
|
|
96
60
|
},
|
|
@@ -143,7 +107,7 @@ function crossDomainClient(opts = {}) {
|
|
|
143
107
|
options
|
|
144
108
|
};
|
|
145
109
|
options = options || {};
|
|
146
|
-
const cookie = getCookie(storage
|
|
110
|
+
const cookie = getCookie(readStoredCookies(storage, cookieName));
|
|
147
111
|
writeServerAuthCookie(cookie);
|
|
148
112
|
options.credentials = getAuthRequestCredentials(cookie);
|
|
149
113
|
options.headers = {
|
|
@@ -181,6 +145,8 @@ function createCamoxAuthClient(apiUrl) {
|
|
|
181
145
|
/**
|
|
182
146
|
* Process a `?ott=` one-time token from the URL before the provider mounts.
|
|
183
147
|
* Verifies the token against the API backend and notifies the session store.
|
|
148
|
+
* The Worker exchanges a studio sign-in's token before rendering, so this handles a preview
|
|
149
|
+
* link's, and any token the Worker couldn't exchange.
|
|
184
150
|
*
|
|
185
151
|
* Reports completion and explicit handoff failures instead of silently showing live content.
|
|
186
152
|
* Keeps the handoff marker until SSR confirms authentication on the subsequent load.
|
|
@@ -230,7 +196,7 @@ function useProcessOtt(authClient, target, initialAuthenticated = false) {
|
|
|
230
196
|
window.location.reload();
|
|
231
197
|
return;
|
|
232
198
|
} catch {
|
|
233
|
-
setError("Preview sign-in failed. The link may have expired or already been used.
|
|
199
|
+
setError("Preview sign-in failed. The link may have expired or already been used. Restart the dev server for a fresh link.");
|
|
234
200
|
}
|
|
235
201
|
setReady(true);
|
|
236
202
|
})();
|
|
@@ -258,7 +224,7 @@ function useProjectUuid() {
|
|
|
258
224
|
}
|
|
259
225
|
const subscribeToHydration = () => () => {};
|
|
260
226
|
function hasStoredAuthCookie() {
|
|
261
|
-
return getCookie(localStorage
|
|
227
|
+
return getCookie(readStoredCookies(localStorage)) !== "";
|
|
262
228
|
}
|
|
263
229
|
const noSubscription = () => () => {};
|
|
264
230
|
/**
|
package/dist/lib/draft-scope.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { UNNAMED_DEFAULT_LOCALE, localeHeaders } from "./locale-path.js";
|
|
2
|
-
import { getApiClient } from "./api-client.js";
|
|
3
2
|
import { c } from "react/compiler-runtime";
|
|
4
3
|
import * as React from "react";
|
|
5
4
|
import { generateUuidv7 } from "@camox/api-contract/ids";
|
|
6
|
-
import {
|
|
5
|
+
import { DRAFT_CREATE_HEADER, DRAFT_HEADER, DRAFT_SEARCH_PARAM } from "@camox/api-contract/drafts";
|
|
7
6
|
import { LIVE_KEY_SCOPE, scopeOfKey } from "@camox/api-contract/query-keys";
|
|
8
7
|
|
|
9
8
|
//#region src/lib/draft-scope.ts
|
|
@@ -17,22 +16,14 @@ function withoutDraft(href) {
|
|
|
17
16
|
url.searchParams.delete(DRAFT_SEARCH_PARAM);
|
|
18
17
|
return url.href;
|
|
19
18
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
function createDraftScope({ queryClient, browser, developmentMode = buildIsDevelopmentMode(), loadDevelopmentDraftId = async (projectId) => (await getApiClient().drafts.get({ projectId }))?.id }) {
|
|
24
|
-
let current = developmentMode ? DEVELOPMENT_DRAFT : null;
|
|
19
|
+
function createDraftScope({ queryClient, browser }) {
|
|
20
|
+
let current = null;
|
|
25
21
|
let locale = UNNAMED_DEFAULT_LOCALE;
|
|
26
22
|
let pending = null;
|
|
27
|
-
let developmentDraftId;
|
|
28
23
|
let adoptedRender = false;
|
|
29
24
|
const listeners = /* @__PURE__ */ new Set();
|
|
30
25
|
const noticeListeners = /* @__PURE__ */ new Set();
|
|
31
26
|
const pendingNotices = [];
|
|
32
|
-
const draftOfRender = (rendered) => {
|
|
33
|
-
if (!developmentMode) return rendered.draftId ?? null;
|
|
34
|
-
return rendered.refusedDraft ? null : DEVELOPMENT_DRAFT;
|
|
35
|
-
};
|
|
36
27
|
const notify = (move) => {
|
|
37
28
|
for (const listener of listeners) listener({
|
|
38
29
|
draftId: current,
|
|
@@ -75,7 +66,7 @@ function createDraftScope({ queryClient, browser, developmentMode = buildIsDevel
|
|
|
75
66
|
},
|
|
76
67
|
settle: noop
|
|
77
68
|
};
|
|
78
|
-
if (!contentWrite
|
|
69
|
+
if (!contentWrite) return {
|
|
79
70
|
headers: inLocale,
|
|
80
71
|
settle: noop
|
|
81
72
|
};
|
|
@@ -102,7 +93,6 @@ function createDraftScope({ queryClient, browser, developmentMode = buildIsDevel
|
|
|
102
93
|
return {
|
|
103
94
|
current: () => current,
|
|
104
95
|
locale: () => locale,
|
|
105
|
-
developmentMode,
|
|
106
96
|
subscribe(listener) {
|
|
107
97
|
listeners.add(listener);
|
|
108
98
|
return () => listeners.delete(listener);
|
|
@@ -114,7 +104,6 @@ function createDraftScope({ queryClient, browser, developmentMode = buildIsDevel
|
|
|
114
104
|
return true;
|
|
115
105
|
},
|
|
116
106
|
hrefFor(to, { from, draft } = {}) {
|
|
117
|
-
if (developmentMode) return to;
|
|
118
107
|
const base = new URL(from ?? browser?.location.href ?? "http://camox.local");
|
|
119
108
|
const target = new URL(to, base);
|
|
120
109
|
if (target.origin !== base.origin) return to;
|
|
@@ -131,7 +120,7 @@ function createDraftScope({ queryClient, browser, developmentMode = buildIsDevel
|
|
|
131
120
|
replaceUrl(null);
|
|
132
121
|
if (rendered.refusedDraft.notice) report(rendered.refusedDraft.notice);
|
|
133
122
|
}
|
|
134
|
-
const next =
|
|
123
|
+
const next = rendered.draftId ?? null;
|
|
135
124
|
if (next !== null) pending = null;
|
|
136
125
|
const firstRender = !adoptedRender;
|
|
137
126
|
adoptedRender = true;
|
|
@@ -149,7 +138,6 @@ function createDraftScope({ queryClient, browser, developmentMode = buildIsDevel
|
|
|
149
138
|
},
|
|
150
139
|
leave(ended, { notice = false } = {}) {
|
|
151
140
|
queryClient.invalidateQueries({ queryKey: ["camox"] });
|
|
152
|
-
if (developmentMode) return false;
|
|
153
141
|
pending = null;
|
|
154
142
|
current = null;
|
|
155
143
|
replaceUrl(null);
|
|
@@ -158,19 +146,11 @@ function createDraftScope({ queryClient, browser, developmentMode = buildIsDevel
|
|
|
158
146
|
...ended
|
|
159
147
|
});
|
|
160
148
|
notify("left");
|
|
161
|
-
return true;
|
|
162
149
|
},
|
|
163
150
|
onNotice(listener) {
|
|
164
151
|
noticeListeners.add(listener);
|
|
165
152
|
for (const notice of pendingNotices.splice(0)) listener(notice);
|
|
166
153
|
return () => noticeListeners.delete(listener);
|
|
167
|
-
},
|
|
168
|
-
async keyScopeOfDraft(draftId, projectId) {
|
|
169
|
-
if (current !== DEVELOPMENT_DRAFT) return draftId;
|
|
170
|
-
developmentDraftId ??= loadDevelopmentDraftId(projectId).catch(() => {
|
|
171
|
-
developmentDraftId = void 0;
|
|
172
|
-
});
|
|
173
|
-
return draftId === await developmentDraftId ? DEVELOPMENT_DRAFT : draftId;
|
|
174
154
|
}
|
|
175
155
|
};
|
|
176
156
|
}
|
|
@@ -6,7 +6,7 @@ function validatePreviewTarget(raw, target) {
|
|
|
6
6
|
const expected = JSON.parse(raw);
|
|
7
7
|
if (expected.projectUuid === target.projectUuid && typeof expected.apiUrl === "string" && expected.apiUrl.replace(/\/+$/, "") === target.apiUrl.replace(/\/+$/, "")) return null;
|
|
8
8
|
} catch {}
|
|
9
|
-
return "
|
|
9
|
+
return "This sign-in link is for another project or backend. Open the one your dev server printed.";
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
//#endregion
|
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
//#region src/lib/server-auth-cookie.ts
|
|
2
2
|
const SERVER_AUTH_COOKIE_NAME = "camox_auth_cookie";
|
|
3
|
+
/** How long the mirror lasts. The API still refuses a session that expired before it. */
|
|
4
|
+
const SERVER_AUTH_COOKIE_MAX_AGE = 2592e3;
|
|
3
5
|
function buildClearServerAuthCookieHeader() {
|
|
4
6
|
return `${SERVER_AUTH_COOKIE_NAME}=; Path=/; SameSite=Lax; Max-Age=0`;
|
|
5
7
|
}
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
/** Sets the mirror to a session, as a `Cookie` header's value. */
|
|
9
|
+
function buildServerAuthCookieHeader(cookie, { secure }) {
|
|
10
|
+
return `${SERVER_AUTH_COOKIE_NAME}=${encodeURIComponent(cookie)}; Path=/; SameSite=Lax; Max-Age=${SERVER_AUTH_COOKIE_MAX_AGE}${secure ? "; Secure" : ""}`;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The session to forward to the API for validation; cookie presence is not authentication. Only
|
|
14
|
+
* the studio's session counts, which the SDK mirrors into `camox_auth_cookie`. Better Auth's own
|
|
15
|
+
* cookies don't: on a Custom Domain like camox.ai they're the dashboard's session, set for every
|
|
16
|
+
* host (ADR 0028). Mirrored in apps/dispatch/src/previews.ts: keep the two in sync.
|
|
9
17
|
*/
|
|
10
18
|
function getServerAuthCookieHeader(headers) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
return readServerAuthCookie(headers.get("Cookie") ?? "");
|
|
20
|
+
}
|
|
21
|
+
/** The mirror's session in a `Cookie` header's value, or `document.cookie`. */
|
|
22
|
+
function readServerAuthCookie(cookieHeader) {
|
|
23
|
+
const mirror = cookieHeader.split(";").map((part) => part.trim()).find((part) => part.startsWith(`${SERVER_AUTH_COOKIE_NAME}=`));
|
|
24
|
+
if (!mirror) return "";
|
|
25
|
+
try {
|
|
26
|
+
return decodeURIComponent(mirror.slice(18));
|
|
27
|
+
} catch {
|
|
28
|
+
return "";
|
|
29
|
+
}
|
|
18
30
|
}
|
|
19
31
|
|
|
20
32
|
//#endregion
|
|
21
|
-
export { SERVER_AUTH_COOKIE_NAME, buildClearServerAuthCookieHeader, getServerAuthCookieHeader };
|
|
33
|
+
export { SERVER_AUTH_COOKIE_NAME, buildClearServerAuthCookieHeader, buildServerAuthCookieHeader, getServerAuthCookieHeader, readServerAuthCookie };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
//#region src/lib/stored-auth-cookies.ts
|
|
2
|
+
function parseSetCookieHeader(header) {
|
|
3
|
+
const cookieMap = /* @__PURE__ */ new Map();
|
|
4
|
+
header.split(", ").forEach((cookie) => {
|
|
5
|
+
const [nameValue, ...attributes] = cookie.split("; ");
|
|
6
|
+
const [name, value] = nameValue.split("=");
|
|
7
|
+
const cookieObj = { value };
|
|
8
|
+
attributes.forEach((attr) => {
|
|
9
|
+
const [attrName, attrValue] = attr.split("=");
|
|
10
|
+
cookieObj[attrName.toLowerCase()] = attrValue;
|
|
11
|
+
});
|
|
12
|
+
cookieMap.set(name, cookieObj);
|
|
13
|
+
});
|
|
14
|
+
return cookieMap;
|
|
15
|
+
}
|
|
16
|
+
function getSetCookie(header, prevCookie) {
|
|
17
|
+
const parsed = parseSetCookieHeader(header);
|
|
18
|
+
let toSetCookie = {};
|
|
19
|
+
parsed.forEach((cookie, key) => {
|
|
20
|
+
const expiresAt = cookie["expires"];
|
|
21
|
+
const maxAge = cookie["max-age"];
|
|
22
|
+
let expires = null;
|
|
23
|
+
if (expiresAt) expires = new Date(String(expiresAt));
|
|
24
|
+
else if (maxAge) expires = new Date(Date.now() + Number(maxAge) * 1e3);
|
|
25
|
+
toSetCookie[key] = {
|
|
26
|
+
value: cookie["value"],
|
|
27
|
+
expires: expires ? expires.toISOString() : null
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
if (prevCookie) try {
|
|
31
|
+
toSetCookie = {
|
|
32
|
+
...JSON.parse(prevCookie),
|
|
33
|
+
...toSetCookie
|
|
34
|
+
};
|
|
35
|
+
} catch {}
|
|
36
|
+
return JSON.stringify(toSetCookie);
|
|
37
|
+
}
|
|
38
|
+
function getCookie(cookie) {
|
|
39
|
+
let parsed = {};
|
|
40
|
+
try {
|
|
41
|
+
parsed = JSON.parse(cookie);
|
|
42
|
+
} catch {}
|
|
43
|
+
const parts = [];
|
|
44
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
45
|
+
if (value.expires && new Date(value.expires) < /* @__PURE__ */ new Date()) continue;
|
|
46
|
+
parts.push(`${key}=${value.value}`);
|
|
47
|
+
}
|
|
48
|
+
return parts.join("; ");
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The stored cookies with those of a `Cookie` header's value added, when it holds one they don't:
|
|
52
|
+
* a session the website's Worker signed in with. Null when they hold it already, even expired.
|
|
53
|
+
*/
|
|
54
|
+
function withCookieHeader(stored, header) {
|
|
55
|
+
let parsed = {};
|
|
56
|
+
try {
|
|
57
|
+
parsed = JSON.parse(stored);
|
|
58
|
+
} catch {}
|
|
59
|
+
let added = false;
|
|
60
|
+
for (const pair of header.split("; ")) {
|
|
61
|
+
const separator = pair.indexOf("=");
|
|
62
|
+
if (separator <= 0) continue;
|
|
63
|
+
const name = pair.slice(0, separator);
|
|
64
|
+
const value = pair.slice(separator + 1);
|
|
65
|
+
if (parsed[name]?.value === value) continue;
|
|
66
|
+
parsed[name] = {
|
|
67
|
+
value,
|
|
68
|
+
expires: null
|
|
69
|
+
};
|
|
70
|
+
added = true;
|
|
71
|
+
}
|
|
72
|
+
return added ? JSON.stringify(parsed) : null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
//#endregion
|
|
76
|
+
export { getCookie, getSetCookie, parseSetCookieHeader, withCookieHeader };
|
package/dist/lib/studio-reads.js
CHANGED
|
@@ -484,7 +484,7 @@ function createStudioCache({ queryClient, scope, api, runtimeJson = (endpoint, b
|
|
|
484
484
|
message,
|
|
485
485
|
projectId
|
|
486
486
|
});
|
|
487
|
-
const keyScope = message.draftId
|
|
487
|
+
const keyScope = message.draftId;
|
|
488
488
|
await Promise.all(message.targets.map((queryKey) => queryClient.invalidateQueries({
|
|
489
489
|
queryKey,
|
|
490
490
|
predicate: keyScope === null ? void 0 : (query) => scopeOfKey(query.queryKey) === keyScope
|
package/dist/lib/use-thread.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { apiSocketOptions } from "./api-socket.js";
|
|
2
2
|
import { c } from "react/compiler-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import { DEVELOPMENT_DRAFT } from "@camox/api-contract/drafts";
|
|
5
4
|
import { usePartySocket } from "partysocket/react";
|
|
6
5
|
import { EMPTY_THREAD_STATE, THREAD_ENDED_CLOSE_CODE, reduceThreadFrame, threadViewOf } from "@camox/api-contract/threads";
|
|
7
6
|
|
|
@@ -11,10 +10,10 @@ const OPEN = 1;
|
|
|
11
10
|
/**
|
|
12
11
|
* Follows a thread in a project over its socket, folding Pi's events into the thread's view: the
|
|
13
12
|
* signed-in editor's Live thread when `draftId` is null, or the draft's thread, which `draftId`
|
|
14
|
-
* names
|
|
13
|
+
* names. A message is resent with its
|
|
15
14
|
* operation id each time the thread shows itself after the socket opens, until it accepts it,
|
|
16
15
|
* which records it once, or turns it down. A draft's thread that ended with its draft isn't
|
|
17
|
-
* reconnected to
|
|
16
|
+
* reconnected to. Mount it once
|
|
18
17
|
* per project and draft.
|
|
19
18
|
*
|
|
20
19
|
* When the agent on Live hands a request off to a draft it started, the studio that sent a
|
|
@@ -25,7 +24,7 @@ const OPEN = 1;
|
|
|
25
24
|
* of only, so that the studio follows the agent; teammates' runs leave it where it is.
|
|
26
25
|
*/
|
|
27
26
|
function useThread(apiUrl, projectId, draftId, t0) {
|
|
28
|
-
const $ = c(
|
|
27
|
+
const $ = c(46);
|
|
29
28
|
let t1;
|
|
30
29
|
if ($[0] !== t0) {
|
|
31
30
|
t1 = t0 === void 0 ? {} : t0;
|
|
@@ -71,17 +70,14 @@ function useThread(apiUrl, projectId, draftId, t0) {
|
|
|
71
70
|
basePath: draftId ? `threads/draft/${projectId}/${draftId}` : `threads/live/${projectId}`,
|
|
72
71
|
maxEnqueuedMessages: 0,
|
|
73
72
|
shouldReconnectOnClose: _temp,
|
|
74
|
-
onClose(event_0) {
|
|
75
|
-
if (event_0.code === THREAD_ENDED_CLOSE_CODE && draftId === DEVELOPMENT_DRAFT) socket.reconnect();
|
|
76
|
-
},
|
|
77
73
|
onOpen() {
|
|
78
74
|
shown.current = false;
|
|
79
75
|
},
|
|
80
|
-
onMessage(
|
|
81
|
-
if (typeof
|
|
76
|
+
onMessage(event_0) {
|
|
77
|
+
if (typeof event_0.data !== "string") return;
|
|
82
78
|
let frame;
|
|
83
79
|
try {
|
|
84
|
-
frame = JSON.parse(
|
|
80
|
+
frame = JSON.parse(event_0.data);
|
|
85
81
|
} catch {
|
|
86
82
|
return;
|
|
87
83
|
}
|
|
@@ -156,10 +152,10 @@ function useThread(apiUrl, projectId, draftId, t0) {
|
|
|
156
152
|
let t9;
|
|
157
153
|
if ($[23] !== socket || $[24] !== unaccepted) {
|
|
158
154
|
t9 = () => {
|
|
159
|
-
for (const [operationId_2,
|
|
155
|
+
for (const [operationId_2, message] of unaccepted) transmit(socket, {
|
|
160
156
|
type: "send",
|
|
161
157
|
operationId: operationId_2,
|
|
162
|
-
|
|
158
|
+
...message
|
|
163
159
|
});
|
|
164
160
|
};
|
|
165
161
|
$[23] = socket;
|
|
@@ -184,6 +180,7 @@ function useThread(apiUrl, projectId, draftId, t0) {
|
|
|
184
180
|
} else t11 = $[30];
|
|
185
181
|
React.useEffect(t10, t11);
|
|
186
182
|
let t12;
|
|
183
|
+
let t13;
|
|
187
184
|
if ($[31] !== socket) {
|
|
188
185
|
t12 = () => {
|
|
189
186
|
const resync = () => {
|
|
@@ -192,44 +189,47 @@ function useThread(apiUrl, projectId, draftId, t0) {
|
|
|
192
189
|
document.addEventListener("visibilitychange", resync);
|
|
193
190
|
return () => document.removeEventListener("visibilitychange", resync);
|
|
194
191
|
};
|
|
192
|
+
t13 = [socket];
|
|
195
193
|
$[31] = socket;
|
|
196
194
|
$[32] = t12;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
t13 = [
|
|
201
|
-
|
|
202
|
-
$[34] = t13;
|
|
203
|
-
} else t13 = $[34];
|
|
195
|
+
$[33] = t13;
|
|
196
|
+
} else {
|
|
197
|
+
t12 = $[32];
|
|
198
|
+
t13 = $[33];
|
|
199
|
+
}
|
|
204
200
|
React.useEffect(t12, t13);
|
|
205
201
|
let t14;
|
|
206
|
-
if ($[
|
|
207
|
-
t14 = (
|
|
202
|
+
if ($[34] !== sent || $[35] !== socket) {
|
|
203
|
+
t14 = (text, where) => {
|
|
208
204
|
const operationId_3 = crypto.randomUUID();
|
|
205
|
+
const message_0 = where ? {
|
|
206
|
+
text,
|
|
207
|
+
where
|
|
208
|
+
} : { text };
|
|
209
209
|
sent.add(operationId_3);
|
|
210
210
|
setError(void 0);
|
|
211
|
-
setUnaccepted((current_3) => new Map(current_3).set(operationId_3,
|
|
211
|
+
setUnaccepted((current_3) => new Map(current_3).set(operationId_3, message_0));
|
|
212
212
|
transmit(socket, {
|
|
213
213
|
type: "send",
|
|
214
214
|
operationId: operationId_3,
|
|
215
|
-
|
|
215
|
+
...message_0
|
|
216
216
|
});
|
|
217
217
|
};
|
|
218
|
-
$[
|
|
219
|
-
$[
|
|
220
|
-
$[
|
|
221
|
-
} else t14 = $[
|
|
218
|
+
$[34] = sent;
|
|
219
|
+
$[35] = socket;
|
|
220
|
+
$[36] = t14;
|
|
221
|
+
} else t14 = $[36];
|
|
222
222
|
const send = t14;
|
|
223
223
|
let t15;
|
|
224
|
-
if ($[
|
|
224
|
+
if ($[37] !== socket) {
|
|
225
225
|
t15 = () => transmit(socket, { type: "stop" });
|
|
226
|
-
$[
|
|
227
|
-
$[
|
|
228
|
-
} else t15 = $[
|
|
226
|
+
$[37] = socket;
|
|
227
|
+
$[38] = t15;
|
|
228
|
+
} else t15 = $[38];
|
|
229
229
|
const stop = t15;
|
|
230
230
|
const t16 = unaccepted.size > 0;
|
|
231
231
|
let t17;
|
|
232
|
-
if ($[
|
|
232
|
+
if ($[39] !== error || $[40] !== send || $[41] !== stop || $[42] !== t16 || $[43] !== touched || $[44] !== view) {
|
|
233
233
|
t17 = {
|
|
234
234
|
view,
|
|
235
235
|
sending: t16,
|
|
@@ -238,14 +238,14 @@ function useThread(apiUrl, projectId, draftId, t0) {
|
|
|
238
238
|
error,
|
|
239
239
|
touched
|
|
240
240
|
};
|
|
241
|
-
$[
|
|
242
|
-
$[
|
|
243
|
-
$[
|
|
244
|
-
$[
|
|
245
|
-
$[
|
|
246
|
-
$[
|
|
247
|
-
$[
|
|
248
|
-
} else t17 = $[
|
|
241
|
+
$[39] = error;
|
|
242
|
+
$[40] = send;
|
|
243
|
+
$[41] = stop;
|
|
244
|
+
$[42] = t16;
|
|
245
|
+
$[43] = touched;
|
|
246
|
+
$[44] = view;
|
|
247
|
+
$[45] = t17;
|
|
248
|
+
} else t17 = $[45];
|
|
249
249
|
return t17;
|
|
250
250
|
}
|
|
251
251
|
function _temp2(count) {
|
package/dist/package.js
CHANGED