camox 0.59.0 → 0.61.0

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.
Files changed (55) hide show
  1. package/dist/core/createApp.d.ts +8 -8
  2. package/dist/core/createBlock.d.ts +1 -2
  3. package/dist/core/createLayout.d.ts +10 -2
  4. package/dist/core/createLayout.js +1 -3
  5. package/dist/core/editing/BlockEditingRuntime.d.ts +1 -0
  6. package/dist/core/editing/CompleteBlockEditingRuntime.js +12 -9
  7. package/dist/core/editing/createEditableBlock.d.ts +4 -4
  8. package/dist/core/editing/createEditableBlock.js +20 -26
  9. package/dist/core/lib/artifactData.js +2 -2
  10. package/dist/core/lib/contentType.js +5 -4
  11. package/dist/features/preview/components/SelectionEditor.js +1 -1
  12. package/dist/features/renderer/RendererApp.js +187 -103
  13. package/dist/features/renderer/rendererHost.js +23 -16
  14. package/dist/features/renderer/studioConnection.js +8 -4
  15. package/dist/features/runtime/loopbackFetch.d.ts +8 -0
  16. package/dist/features/runtime/publicCache.d.ts +21 -0
  17. package/dist/features/runtime/publishingDraft.d.ts +4 -0
  18. package/dist/features/runtime/runtime.js +54 -3
  19. package/dist/features/runtime/worker.js +1 -4
  20. package/dist/features/runtime/workerRequest.d.ts +8 -0
  21. package/dist/features/runtime/workerRuntime.d.ts +5 -0
  22. package/dist/features/runtime/workerRuntime.js +6 -0
  23. package/dist/features/sdkBundle/buildSdkBundle.d.ts +40 -0
  24. package/dist/features/sdkBundle/buildSdkBundle.js +323 -0
  25. package/dist/features/sdkBundle/localSdkBundle.d.ts +44 -0
  26. package/dist/features/sdkBundle/localSdkBundle.js +162 -0
  27. package/dist/features/sdkBundle/sdkBundle.d.ts +3 -0
  28. package/dist/features/sdkBundle/sdkBundle.js +4 -0
  29. package/dist/features/sdkBundle/sdkBundleName.d.ts +59 -0
  30. package/dist/features/sdkBundle/sdkBundleName.js +164 -0
  31. package/dist/features/sdkBundle/specifiers.d.ts +34 -0
  32. package/dist/features/sdkBundle/specifiers.js +146 -0
  33. package/dist/features/settings/SocialProfilesSettings.js +284 -151
  34. package/dist/features/settings/useProjectMutation.js +6 -5
  35. package/dist/features/studio/FollowAgentProvider.js +71 -12
  36. package/dist/features/studio/components/ChatWidget.js +85 -43
  37. package/dist/features/studio/components/Patrol.js +311 -208
  38. package/dist/features/studio/components/Squareling.js +164 -66
  39. package/dist/features/studio/components/ThreadComposer.js +139 -69
  40. package/dist/features/studio/components/ThreadMessages.js +115 -45
  41. package/dist/features/studio/editorWhereContext.js +11 -0
  42. package/dist/features/studio/useEditorSelection.js +135 -0
  43. package/dist/features/vite/hostedChecks.js +1 -1
  44. package/dist/features/vite/runtimeDev.js +2 -1
  45. package/dist/features/vite/sdkBundleBuild.js +74 -0
  46. package/dist/features/vite/staticAssetHeaders.js +7 -4
  47. package/dist/features/vite/vite.d.ts +0 -2
  48. package/dist/features/vite/vite.js +33 -3
  49. package/dist/lib/auth.js +24 -58
  50. package/dist/lib/server-auth-cookie.js +12 -2
  51. package/dist/lib/stored-auth-cookies.js +76 -0
  52. package/dist/lib/use-thread.js +9 -5
  53. package/dist/package.js +1 -1
  54. package/dist/studio.css +1 -1
  55. package/package.json +17 -4
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 { SERVER_AUTH_COOKIE_NAME, buildClearServerAuthCookieHeader, getServerAuthCookieHeader } from "./server-auth-cookie.js";
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:" ? "; Secure" : "";
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 = `${SERVER_AUTH_COOKIE_NAME}=${encodeURIComponent(cookie)}; Path=/; SameSite=Lax; Max-Age=2592000${secure}`;
18
+ document.cookie = buildServerAuthCookieHeader(cookie, { secure });
18
19
  }
19
- function parseSetCookieHeader(header) {
20
- const cookieMap = /* @__PURE__ */ new Map();
21
- header.split(", ").forEach((cookie) => {
22
- const [nameValue, ...attributes] = cookie.split("; ");
23
- const [name, value] = nameValue.split("=");
24
- const cookieObj = { value };
25
- attributes.forEach((attr) => {
26
- const [attrName, attrValue] = attr.split("=");
27
- cookieObj[attrName.toLowerCase()] = attrValue;
28
- });
29
- cookieMap.set(name, cookieObj);
30
- });
31
- return cookieMap;
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.getItem("better-auth_cookie") || "{}");
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.getItem(cookieName) || "{}");
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.
@@ -258,7 +224,7 @@ function useProjectUuid() {
258
224
  }
259
225
  const subscribeToHydration = () => () => {};
260
226
  function hasStoredAuthCookie() {
261
- return getCookie(localStorage.getItem("better-auth_cookie") || "{}") !== "";
227
+ return getCookie(readStoredCookies(localStorage)) !== "";
262
228
  }
263
229
  const noSubscription = () => () => {};
264
230
  /**
@@ -1,8 +1,14 @@
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
  }
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
+ }
6
12
  /**
7
13
  * The session to forward to the API for validation; cookie presence is not authentication. Only
8
14
  * the studio's session counts, which the SDK mirrors into `camox_auth_cookie`. Better Auth's own
@@ -10,7 +16,11 @@ function buildClearServerAuthCookieHeader() {
10
16
  * host (ADR 0028). Mirrored in apps/dispatch/src/previews.ts: keep the two in sync.
11
17
  */
12
18
  function getServerAuthCookieHeader(headers) {
13
- const mirror = (headers.get("Cookie") ?? "").split(";").map((part) => part.trim()).find((part) => part.startsWith(`${SERVER_AUTH_COOKIE_NAME}=`));
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}=`));
14
24
  if (!mirror) return "";
15
25
  try {
16
26
  return decodeURIComponent(mirror.slice(18));
@@ -20,4 +30,4 @@ function getServerAuthCookieHeader(headers) {
20
30
  }
21
31
 
22
32
  //#endregion
23
- 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 };
@@ -152,10 +152,10 @@ function useThread(apiUrl, projectId, draftId, t0) {
152
152
  let t9;
153
153
  if ($[23] !== socket || $[24] !== unaccepted) {
154
154
  t9 = () => {
155
- for (const [operationId_2, text] of unaccepted) transmit(socket, {
155
+ for (const [operationId_2, message] of unaccepted) transmit(socket, {
156
156
  type: "send",
157
157
  operationId: operationId_2,
158
- text
158
+ ...message
159
159
  });
160
160
  };
161
161
  $[23] = socket;
@@ -200,15 +200,19 @@ function useThread(apiUrl, projectId, draftId, t0) {
200
200
  React.useEffect(t12, t13);
201
201
  let t14;
202
202
  if ($[34] !== sent || $[35] !== socket) {
203
- t14 = (text_0) => {
203
+ t14 = (text, where) => {
204
204
  const operationId_3 = crypto.randomUUID();
205
+ const message_0 = where ? {
206
+ text,
207
+ where
208
+ } : { text };
205
209
  sent.add(operationId_3);
206
210
  setError(void 0);
207
- setUnaccepted((current_3) => new Map(current_3).set(operationId_3, text_0));
211
+ setUnaccepted((current_3) => new Map(current_3).set(operationId_3, message_0));
208
212
  transmit(socket, {
209
213
  type: "send",
210
214
  operationId: operationId_3,
211
- text: text_0
215
+ ...message_0
212
216
  });
213
217
  };
214
218
  $[34] = sent;
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.59.0";
2
+ var version = "0.61.0";
3
3
 
4
4
  //#endregion
5
5
  export { version };