@jxsuite/protocol 6.3.0 → 6.4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jxsuite/protocol",
3
- "version": "6.3.0",
3
+ "version": "6.4.0",
4
4
  "description": "The Studio Backend Protocol — wire types and the canonical route table every Jx Studio backend implements",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -15,6 +15,7 @@
15
15
  "exports": {
16
16
  ".": "./src/index.ts",
17
17
  "./git-scope": "./src/git-scope.ts",
18
+ "./preview-harness": "./src/preview-harness.ts",
18
19
  "./problem": "./src/problem.ts",
19
20
  "./problems": "./src/problems.ts",
20
21
  "./routes": "./src/routes.ts",
@@ -28,6 +29,6 @@
28
29
  "test:coverage": "bun test --isolate --coverage"
29
30
  },
30
31
  "dependencies": {
31
- "@jxsuite/schema": "^5.6.0"
32
+ "@jxsuite/schema": "^6.0.0"
32
33
  }
33
34
  }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The address a live preview origin runs one component or one layout at, on its own.
3
+ *
4
+ * A page has a route and these do not, so the address is a contract rather than something either
5
+ * side may derive: Studio writes it and a backend that declares `previewSite` answers it
6
+ * (`server.md` §3.4, `studio.md` §10.1). Both read it from here so they cannot disagree.
7
+ *
8
+ * A component's test values travel IN the address, as a `props` query parameter holding a JSON
9
+ * object, so a reload, a live-reload and a retarget all render the same thing with no store kept
10
+ * alive behind them. What an address may make a backend do is the backend's to bound; what this
11
+ * module bounds is its length.
12
+ *
13
+ * @module
14
+ * @docs extending/embedding/platform-adapter
15
+ */
16
+
17
+ import type { JsonValue } from "./types";
18
+
19
+ /** What a harness address starts with; the document's project path follows. */
20
+ export const HARNESS_ROUTE = "/__jx_live__/harness/";
21
+
22
+ /**
23
+ * The longest query a harness address carries, in characters as sent.
24
+ *
25
+ * Test values are typed into one small field each, so this is generous, and it sits well under the
26
+ * request line a server will read at all: past that the answer would be a bare 431 with nothing to
27
+ * say why.
28
+ */
29
+ export const HARNESS_QUERY_MAX = 8192;
30
+
31
+ /** A harness address, and whether its test values had to be left out of it. */
32
+ export interface HarnessAddress {
33
+ /** The origin-relative address: path, then the `props` query when there is one. */
34
+ path: string;
35
+ /** True when there were test values and their encoded form passed {@link HARNESS_QUERY_MAX}. */
36
+ dropped: boolean;
37
+ }
38
+
39
+ /**
40
+ * The harness address for one document.
41
+ *
42
+ * Each path segment is encoded on its own, so a file name holding `?` or `#` stays part of the path
43
+ * instead of starting a query or a fragment. Values too large for an address are left out rather
44
+ * than truncated: half a JSON object is not a smaller set of values, and the document still runs
45
+ * with its defaults.
46
+ *
47
+ * @param documentPath The document's project path, e.g. `components/user-card.json`.
48
+ * @param props The test values to carry, when the document is a component that has any.
49
+ */
50
+ export function harnessAddress(
51
+ documentPath: string,
52
+ props?: Readonly<Record<string, JsonValue>> | null,
53
+ ): HarnessAddress {
54
+ const route = `${HARNESS_ROUTE}${documentPath
55
+ .split("/")
56
+ .map((segment) => encodeURIComponent(segment))
57
+ .join("/")}`;
58
+ if (!props || Object.keys(props).length === 0) {
59
+ return { dropped: false, path: route };
60
+ }
61
+ const query = `?props=${encodeURIComponent(JSON.stringify(props))}`;
62
+ return query.length > HARNESS_QUERY_MAX
63
+ ? { dropped: true, path: route }
64
+ : { dropped: false, path: `${route}${query}` };
65
+ }