@valbuild/shared 0.148.2 → 0.148.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.
- package/CHANGELOG.md +51 -0
- package/dist/declarations/src/internal/ApiRoutes.d.ts +39 -0
- package/dist/declarations/src/internal/demo.d.ts +146 -0
- package/internal/dist/valbuild-shared-internal.cjs.dev.js +116 -0
- package/internal/dist/valbuild-shared-internal.cjs.prod.js +116 -0
- package/internal/dist/valbuild-shared-internal.esm.js +116 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# @valbuild/shared
|
|
2
2
|
|
|
3
|
+
## 0.148.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#902](https://github.com/valbuild/val/pull/902) [`b580292`](https://github.com/valbuild/val/commit/b580292ac3c335b055f5ed5f18d6a12d075169c7) Thanks [@freekh](https://github.com/freekh)! - The demo has a script: `<ValApp demo={{ tours, audiences }}>`. Instead of a tour that opens by itself, the demo card asks "What brings you here?" and lists short tours for the answer, each ticked off once done. `/val?tour=<id>` starts one from a link.
|
|
8
|
+
|
|
9
|
+
A tour can start on a page of its own (`start`). A step can ask for a new page (`moveOn: { newPage }`), write any value or add one (`moveOn: { edit, value, add }`), and show the code behind what it is about (`code`).
|
|
10
|
+
|
|
11
|
+
## 0.148.3
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#881](https://github.com/valbuild/val/pull/881) [`0139436`](https://github.com/valbuild/val/commit/0139436426142d91cbb29ec6c696dfb86f34ab9d) Thanks [@freekh](https://github.com/freekh)! - The content analytics script. With analytics on (it is off by default, and turned on in a hosted project's settings), a TanStack site counts which content each visitor's page **rendered** and which they actually **viewed** (at least half on screen for a second), and sends it to `/api/val/analytics`.
|
|
16
|
+
|
|
17
|
+
- No cookies, no storage, no visitor IDs. Each page view also says where it came from (the referring site's host and any `utm_source` / `utm_medium` / `utm_campaign`) and whether it was a phone, tablet or desktop.
|
|
18
|
+
- A page is sent as its route's pattern (`/posts/$postId`), never its address, so a path that holds something about one visitor (an order number, a token) is never stored. `startValAnalytics` takes this as `routeFor`; `ValProvider` passes TanStack's matched route.
|
|
19
|
+
- Editors are never counted: nothing is sent in draft mode, in the Studio, with Val enabled, or at a proposal's address, and nothing from automated browsers. A page the browser prerenders counts nothing until it is shown.
|
|
20
|
+
- The script is the new `@valbuild/react/analytics` entry, loaded only for visitors of a site with analytics on, after the page has hydrated. It imports nothing else from Val.
|
|
21
|
+
- Storing the counts and showing them is part of Val's hosting, which takes these beacons before they reach the site. Anywhere else, `/api/val/analytics` checks each beacon and stores nothing; in local development, with `VAL_DEBUG=1`, it logs a line per beacon, so you can see it working.
|
|
22
|
+
- `ValProvider`'s Studio check now matches `/val` and what is below it only, not every route starting with those letters (`/values`). The same fix is in `@valbuild/next`.
|
|
23
|
+
|
|
24
|
+
- [#896](https://github.com/valbuild/val/pull/896) [`5eff8a0`](https://github.com/valbuild/val/commit/5eff8a055a4ef50d476797c28f9c3e50deb73c89) Thanks [@freekh](https://github.com/freekh)! - A demo's tour can now be written by the site: `<ValApp demo={{ tour }}>`, with each step as data (`ValDemoTourStep`), so what it says changes with the site rather than with a Val release.
|
|
25
|
+
|
|
26
|
+
It is drawn as a ring around what a step is about, with nothing dimmed and the Studio usable underneath, and a step can move on by itself once the visitor has done what it asks:
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
const tour: ValDemoTourStep[] = [
|
|
30
|
+
{
|
|
31
|
+
id: "click",
|
|
32
|
+
title: "This is Val",
|
|
33
|
+
body: "Click the heading on the page.",
|
|
34
|
+
target: "canvas",
|
|
35
|
+
page: HEADING, // outlined on the page
|
|
36
|
+
moveOn: { open: HEADING },
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "type",
|
|
40
|
+
title: "Change a word",
|
|
41
|
+
body: "The page changes as you type.",
|
|
42
|
+
field: HEADING, // ringed wherever the field is shown
|
|
43
|
+
moveOn: {
|
|
44
|
+
edit: true,
|
|
45
|
+
path: HEADING,
|
|
46
|
+
value: "Coffee, roasted this weekend",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
A step that moves on has **Do it for me**, which does it the way the Studio would, and **Skip**. On a phone the card is a sheet along the bottom. The Studio's own tour is unchanged.
|
|
53
|
+
|
|
3
54
|
## 0.148.2
|
|
4
55
|
|
|
5
56
|
### Patch Changes
|
|
@@ -45,6 +45,27 @@ type CookieValue = EnableCookieValue | {
|
|
|
45
45
|
* this. Shared so client and server agree on the limit.
|
|
46
46
|
*/
|
|
47
47
|
export declare const JSON_ENTRIES_BATCH_MAX = 100;
|
|
48
|
+
export declare const AnalyticsBeacon: z.ZodObject<{
|
|
49
|
+
v: z.ZodLiteral<1>;
|
|
50
|
+
route: z.ZodString;
|
|
51
|
+
cv: z.ZodOptional<z.ZodString>;
|
|
52
|
+
view: z.ZodOptional<z.ZodObject<{
|
|
53
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
54
|
+
utm: z.ZodOptional<z.ZodObject<{
|
|
55
|
+
source: z.ZodOptional<z.ZodString>;
|
|
56
|
+
medium: z.ZodOptional<z.ZodString>;
|
|
57
|
+
campaign: z.ZodOptional<z.ZodString>;
|
|
58
|
+
}, z.core.$strip>>;
|
|
59
|
+
device: z.ZodEnum<{
|
|
60
|
+
phone: "phone";
|
|
61
|
+
tablet: "tablet";
|
|
62
|
+
desktop: "desktop";
|
|
63
|
+
}>;
|
|
64
|
+
}, z.core.$strip>>;
|
|
65
|
+
rendered: z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>;
|
|
66
|
+
viewed: z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>;
|
|
67
|
+
}, z.core.$strip>;
|
|
68
|
+
export type AnalyticsBeacon = z.infer<typeof AnalyticsBeacon>;
|
|
48
69
|
export declare const Api: {
|
|
49
70
|
"/draft/enable": {
|
|
50
71
|
GET: {
|
|
@@ -98,6 +119,24 @@ export declare const Api: {
|
|
|
98
119
|
}, z.core.$strip>]>;
|
|
99
120
|
};
|
|
100
121
|
};
|
|
122
|
+
"/analytics": {
|
|
123
|
+
POST: {
|
|
124
|
+
req: {
|
|
125
|
+
body: z.ZodUnknown;
|
|
126
|
+
};
|
|
127
|
+
res: z.ZodUnion<readonly [z.ZodObject<{
|
|
128
|
+
status: z.ZodLiteral<200>;
|
|
129
|
+
json: z.ZodObject<{
|
|
130
|
+
counted: z.ZodBoolean;
|
|
131
|
+
}, z.core.$strip>;
|
|
132
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
133
|
+
status: z.ZodLiteral<400>;
|
|
134
|
+
json: z.ZodObject<{
|
|
135
|
+
message: z.ZodString;
|
|
136
|
+
}, z.core.$strip>;
|
|
137
|
+
}, z.core.$strip>]>;
|
|
138
|
+
};
|
|
139
|
+
};
|
|
101
140
|
"/draft/stat": {
|
|
102
141
|
GET: {
|
|
103
142
|
req: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { JSONValue } from "@valbuild/core/patch";
|
|
1
2
|
/**
|
|
2
3
|
* A Val demo, as the page hands it to the Studio.
|
|
3
4
|
*
|
|
@@ -23,6 +24,151 @@ export type ValDemoRuntime = {
|
|
|
23
24
|
* refuses uploads before sending anything, and says why.
|
|
24
25
|
*/
|
|
25
26
|
uploads: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* The tour the site wrote, in place of the Studio's own demo tour. See
|
|
29
|
+
* `ValDemoTourStep`. Absent: the Studio's.
|
|
30
|
+
*/
|
|
31
|
+
tour?: ValDemoTourStep[];
|
|
32
|
+
/** The demo script. See `ValDemoOptions.tours`. */
|
|
33
|
+
tours?: ValDemoTour[];
|
|
34
|
+
/** "What brings you here?". See `ValDemoOptions.audiences`. */
|
|
35
|
+
audiences?: ValDemoAudience[];
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* What the site starts the demo with: `<ValApp demo={{ tour }}>`.
|
|
39
|
+
*
|
|
40
|
+
* `demo` alone (`true`) is the same with nothing given.
|
|
41
|
+
*/
|
|
42
|
+
export type ValDemoOptions = {
|
|
43
|
+
/**
|
|
44
|
+
* One tour, behind the demo card's Tour button, opened on a first visit.
|
|
45
|
+
* `tours` replaces it: given both, `tours` is used.
|
|
46
|
+
*/
|
|
47
|
+
tour?: ValDemoTourStep[];
|
|
48
|
+
/**
|
|
49
|
+
* The demo script: short tours the visitor picks from on the demo card,
|
|
50
|
+
* each ticked off once done. A tour can be started from a link too:
|
|
51
|
+
* `/val?tour=<id>`.
|
|
52
|
+
*/
|
|
53
|
+
tours?: ValDemoTour[];
|
|
54
|
+
/**
|
|
55
|
+
* What the demo card asks first, "What brings you here?": each answer is a
|
|
56
|
+
* list of `tours`, by id, and the card shows the list for the answer. With
|
|
57
|
+
* two or more, the Studio adds "Show me everything", all of them in order.
|
|
58
|
+
* Absent: every tour, in the order given.
|
|
59
|
+
*/
|
|
60
|
+
audiences?: ValDemoAudience[];
|
|
61
|
+
};
|
|
62
|
+
/** One item of the demo script. */
|
|
63
|
+
export type ValDemoTour = {
|
|
64
|
+
/** Stable: the answer's list names it, and `?tour=` starts it. */
|
|
65
|
+
id: string;
|
|
66
|
+
title: string;
|
|
67
|
+
/** How long it takes, as the card says it: "30 s", "1 min". */
|
|
68
|
+
duration?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Where the tour starts, as a source path: a page of the site (a page
|
|
71
|
+
* router's module and the page's key). The Studio goes there first, so a
|
|
72
|
+
* tour about the home page is not started on whatever page the last one
|
|
73
|
+
* left open.
|
|
74
|
+
*/
|
|
75
|
+
start?: string;
|
|
76
|
+
steps: ValDemoTourStep[];
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* An answer to "What brings you here?".
|
|
80
|
+
*
|
|
81
|
+
* The first tour of its list is the one the card offers first, with a
|
|
82
|
+
* button of its own: the one to start with.
|
|
83
|
+
*/
|
|
84
|
+
export type ValDemoAudience = {
|
|
85
|
+
id: string;
|
|
86
|
+
/** "I write and edit content". */
|
|
87
|
+
title: string;
|
|
88
|
+
/** What the list has in it, in a line: "Pages, photos, languages". */
|
|
89
|
+
description?: string;
|
|
90
|
+
/** Tours by id, in order. */
|
|
91
|
+
tours: string[];
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* A control of the Studio's a step can point at.
|
|
95
|
+
*
|
|
96
|
+
* The `data-val-tour` markers the Studio puts on them. One that is not on
|
|
97
|
+
* screen (the rail on a phone) leaves the card on its own, so a step's words
|
|
98
|
+
* must work without the arrow: never "this button here".
|
|
99
|
+
*/
|
|
100
|
+
export type ValDemoTourTarget = "canvas" | "pages" | "media" | "data" | "review" | "preview" | "publish" | "ai" | "locale" | "demo" | "utility" | "new-page";
|
|
101
|
+
/** A panel a step opens, so what it is about is on screen behind the card. */
|
|
102
|
+
export type ValDemoTourPanel = "pages" | "media" | "data" | "settings" | "ai";
|
|
103
|
+
/**
|
|
104
|
+
* What moves a step on by itself. A step without one has Next.
|
|
105
|
+
*
|
|
106
|
+
* Each is something the visitor does, because doing it is the lesson, and
|
|
107
|
+
* each has a "Do it for me" that does it the way the Studio would:
|
|
108
|
+
*
|
|
109
|
+
* - `open`: a field at or below this source path is opened -- by clicking it
|
|
110
|
+
* on the page, or anywhere else. Do it for me opens it.
|
|
111
|
+
* - `edit`: a change is made. Do it for me writes `value` at `path` --
|
|
112
|
+
* replacing what is there, or with `add: true` adding it, as a new entry of
|
|
113
|
+
* a record or a new item of a list at that index; without them, it is
|
|
114
|
+
* offered nowhere and the step waits for the visitor.
|
|
115
|
+
* - `newPage`: a page is added. Do it for me adds the page this source path
|
|
116
|
+
* names (a page router's module and the new page's key, `?p="/journal/x"`)
|
|
117
|
+
* the way the New page form does, empty, and opens it.
|
|
118
|
+
* - `panel`: that panel is opened. Do it for me opens it.
|
|
119
|
+
* - `locale`: the language shown is changed. Do it for me picks the next one.
|
|
120
|
+
*/
|
|
121
|
+
export type ValDemoTourMoveOn = {
|
|
122
|
+
open: string;
|
|
123
|
+
} | {
|
|
124
|
+
edit: true;
|
|
125
|
+
path?: string;
|
|
126
|
+
value?: JSONValue;
|
|
127
|
+
add?: boolean;
|
|
128
|
+
} | {
|
|
129
|
+
newPage: string;
|
|
130
|
+
} | {
|
|
131
|
+
panel: ValDemoTourPanel;
|
|
132
|
+
} | {
|
|
133
|
+
locale: true;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* One stop of the demo's tour, as the site writes it.
|
|
137
|
+
*
|
|
138
|
+
* Data rather than components, so the tour can be rewritten -- and tried on
|
|
139
|
+
* people -- without a Val release: the Studio draws it, the site says what it
|
|
140
|
+
* says. Written for someone who has never seen Val.
|
|
141
|
+
*/
|
|
142
|
+
export type ValDemoTourStep = {
|
|
143
|
+
/** Stable, so a test can name a step without matching its words. */
|
|
144
|
+
id: string;
|
|
145
|
+
title: string;
|
|
146
|
+
body: string;
|
|
147
|
+
/** The control this step is about. */
|
|
148
|
+
target?: ValDemoTourTarget;
|
|
149
|
+
/**
|
|
150
|
+
* A field this step is about, as a source path: ringed wherever the Studio
|
|
151
|
+
* shows it -- the page's fields, or the module open in the editor. Takes
|
|
152
|
+
* precedence over `target`, which is what is ringed when the field is not
|
|
153
|
+
* on screen.
|
|
154
|
+
*/
|
|
155
|
+
field?: string;
|
|
156
|
+
/**
|
|
157
|
+
* A place on the page this step is about, as a source path: the page
|
|
158
|
+
* outlines it and brings it into view.
|
|
159
|
+
*/
|
|
160
|
+
page?: string;
|
|
161
|
+
panel?: ValDemoTourPanel;
|
|
162
|
+
moveOn?: ValDemoTourMoveOn;
|
|
163
|
+
/**
|
|
164
|
+
* Code to show in the card: the line of a `.val.ts` behind what the step is
|
|
165
|
+
* about, for a visitor who builds sites. Written by the site, so it has to
|
|
166
|
+
* be kept the same as the file; `file` says which one.
|
|
167
|
+
*/
|
|
168
|
+
code?: {
|
|
169
|
+
file: string;
|
|
170
|
+
text: string;
|
|
171
|
+
};
|
|
26
172
|
};
|
|
27
173
|
declare global {
|
|
28
174
|
var __VAL_DEMO__: ValDemoRuntime | undefined;
|
|
@@ -1782,6 +1782,48 @@ var onlyOneIntQueryParam = onlyOneStringQueryParam.refine(function (arg) {
|
|
|
1782
1782
|
* this. Shared so client and server agree on the limit.
|
|
1783
1783
|
*/
|
|
1784
1784
|
var JSON_ENTRIES_BATCH_MAX = 100;
|
|
1785
|
+
|
|
1786
|
+
/**
|
|
1787
|
+
* Content analytics, wire format version 1: the beacon the browser script
|
|
1788
|
+
* (`@valbuild/react/analytics`) sends to `POST /api/val/analytics`. Its
|
|
1789
|
+
* `AnalyticsBeacon` type is written by hand there, because that code is on
|
|
1790
|
+
* every visitor's page and must not load zod; `analytics/beacon.test.ts` in
|
|
1791
|
+
* `@valbuild/react` checks that what it builds parses here.
|
|
1792
|
+
*/
|
|
1793
|
+
/*
|
|
1794
|
+
* The limits the browser script keeps to (`MAX_*` in
|
|
1795
|
+
* `@valbuild/react/analytics`'s `beacon.ts`, which cannot import this). The
|
|
1796
|
+
* endpoint takes anyone's POST, so it checks what it is sent rather than
|
|
1797
|
+
* trusting the sender; `beacon.test.ts` builds beacons at the limits and
|
|
1798
|
+
* parses them here.
|
|
1799
|
+
*/
|
|
1800
|
+
var MAX_ANALYTICS_PATHS_PER_BEACON = 200;
|
|
1801
|
+
var AnalyticsPaths = zod.z.record(zod.z.string().max(512), zod.z.array(zod.z.string().max(1024)).max(MAX_ANALYTICS_PATHS_PER_BEACON));
|
|
1802
|
+
var countAnalyticsPaths = function countAnalyticsPaths(paths) {
|
|
1803
|
+
return Object.values(paths).reduce(function (n, list) {
|
|
1804
|
+
return n + list.length;
|
|
1805
|
+
}, 0);
|
|
1806
|
+
};
|
|
1807
|
+
var AnalyticsBeacon = zod.z.object({
|
|
1808
|
+
v: zod.z.literal(1),
|
|
1809
|
+
route: zod.z.string().max(512),
|
|
1810
|
+
cv: zod.z.string().max(128).optional(),
|
|
1811
|
+
view: zod.z.object({
|
|
1812
|
+
ref: zod.z.string().max(253).optional(),
|
|
1813
|
+
utm: zod.z.object({
|
|
1814
|
+
source: zod.z.string().max(100).optional(),
|
|
1815
|
+
medium: zod.z.string().max(100).optional(),
|
|
1816
|
+
campaign: zod.z.string().max(100).optional()
|
|
1817
|
+
}).optional(),
|
|
1818
|
+
device: zod.z["enum"](["phone", "tablet", "desktop"])
|
|
1819
|
+
}).optional(),
|
|
1820
|
+
rendered: AnalyticsPaths,
|
|
1821
|
+
viewed: AnalyticsPaths
|
|
1822
|
+
}).refine(function (beacon) {
|
|
1823
|
+
return countAnalyticsPaths(beacon.rendered) + countAnalyticsPaths(beacon.viewed) <= MAX_ANALYTICS_PATHS_PER_BEACON;
|
|
1824
|
+
}, {
|
|
1825
|
+
message: "At most ".concat(MAX_ANALYTICS_PATHS_PER_BEACON, " paths a beacon")
|
|
1826
|
+
});
|
|
1785
1827
|
var Api = {
|
|
1786
1828
|
"/draft/enable": {
|
|
1787
1829
|
GET: {
|
|
@@ -1827,6 +1869,27 @@ var Api = {
|
|
|
1827
1869
|
})])
|
|
1828
1870
|
}
|
|
1829
1871
|
},
|
|
1872
|
+
"/analytics": {
|
|
1873
|
+
POST: {
|
|
1874
|
+
// Parsed by the handler rather than here, so a beacon of a version this
|
|
1875
|
+
// server does not know is ignored instead of refused.
|
|
1876
|
+
req: {
|
|
1877
|
+
body: zod.z.unknown()
|
|
1878
|
+
},
|
|
1879
|
+
res: zod.z.union([
|
|
1880
|
+
// `counted` is false wherever nothing stores the counts -- every
|
|
1881
|
+
// server but the hosted platform's, for now.
|
|
1882
|
+
zod.z.object({
|
|
1883
|
+
status: zod.z.literal(200),
|
|
1884
|
+
json: zod.z.object({
|
|
1885
|
+
counted: zod.z["boolean"]()
|
|
1886
|
+
})
|
|
1887
|
+
}), zod.z.object({
|
|
1888
|
+
status: zod.z.literal(400),
|
|
1889
|
+
json: GenericError
|
|
1890
|
+
})])
|
|
1891
|
+
}
|
|
1892
|
+
},
|
|
1830
1893
|
"/draft/stat": {
|
|
1831
1894
|
GET: {
|
|
1832
1895
|
req: {
|
|
@@ -4093,6 +4156,58 @@ function isRetryable(error) {
|
|
|
4093
4156
|
* modules. See `docs/plans/demo-mode.md`.
|
|
4094
4157
|
*/
|
|
4095
4158
|
|
|
4159
|
+
/**
|
|
4160
|
+
* What the site starts the demo with: `<ValApp demo={{ tour }}>`.
|
|
4161
|
+
*
|
|
4162
|
+
* `demo` alone (`true`) is the same with nothing given.
|
|
4163
|
+
*/
|
|
4164
|
+
|
|
4165
|
+
/** One item of the demo script. */
|
|
4166
|
+
|
|
4167
|
+
/**
|
|
4168
|
+
* An answer to "What brings you here?".
|
|
4169
|
+
*
|
|
4170
|
+
* The first tour of its list is the one the card offers first, with a
|
|
4171
|
+
* button of its own: the one to start with.
|
|
4172
|
+
*/
|
|
4173
|
+
|
|
4174
|
+
/**
|
|
4175
|
+
* A control of the Studio's a step can point at.
|
|
4176
|
+
*
|
|
4177
|
+
* The `data-val-tour` markers the Studio puts on them. One that is not on
|
|
4178
|
+
* screen (the rail on a phone) leaves the card on its own, so a step's words
|
|
4179
|
+
* must work without the arrow: never "this button here".
|
|
4180
|
+
*/
|
|
4181
|
+
|
|
4182
|
+
/** A panel a step opens, so what it is about is on screen behind the card. */
|
|
4183
|
+
|
|
4184
|
+
/**
|
|
4185
|
+
* What moves a step on by itself. A step without one has Next.
|
|
4186
|
+
*
|
|
4187
|
+
* Each is something the visitor does, because doing it is the lesson, and
|
|
4188
|
+
* each has a "Do it for me" that does it the way the Studio would:
|
|
4189
|
+
*
|
|
4190
|
+
* - `open`: a field at or below this source path is opened -- by clicking it
|
|
4191
|
+
* on the page, or anywhere else. Do it for me opens it.
|
|
4192
|
+
* - `edit`: a change is made. Do it for me writes `value` at `path` --
|
|
4193
|
+
* replacing what is there, or with `add: true` adding it, as a new entry of
|
|
4194
|
+
* a record or a new item of a list at that index; without them, it is
|
|
4195
|
+
* offered nowhere and the step waits for the visitor.
|
|
4196
|
+
* - `newPage`: a page is added. Do it for me adds the page this source path
|
|
4197
|
+
* names (a page router's module and the new page's key, `?p="/journal/x"`)
|
|
4198
|
+
* the way the New page form does, empty, and opens it.
|
|
4199
|
+
* - `panel`: that panel is opened. Do it for me opens it.
|
|
4200
|
+
* - `locale`: the language shown is changed. Do it for me picks the next one.
|
|
4201
|
+
*/
|
|
4202
|
+
|
|
4203
|
+
/**
|
|
4204
|
+
* One stop of the demo's tour, as the site writes it.
|
|
4205
|
+
*
|
|
4206
|
+
* Data rather than components, so the tour can be rewritten -- and tried on
|
|
4207
|
+
* people -- without a Val release: the Studio draws it, the site says what it
|
|
4208
|
+
* says. Written for someone who has never seen Val.
|
|
4209
|
+
*/
|
|
4210
|
+
|
|
4096
4211
|
/*
|
|
4097
4212
|
* A global `var` rather than a `Window` member: this package is compiled
|
|
4098
4213
|
* without the DOM's types, and a `var` in global scope is also a property of
|
|
@@ -8943,6 +9058,7 @@ exports.parseRoutePattern = getSitemapTree.parseRoutePattern;
|
|
|
8943
9058
|
exports.withValCanvasParam = getSitemapTree.withValCanvasParam;
|
|
8944
9059
|
exports.AA_LARGE = AA_LARGE;
|
|
8945
9060
|
exports.AA_TEXT = AA_TEXT;
|
|
9061
|
+
exports.AnalyticsBeacon = AnalyticsBeacon;
|
|
8946
9062
|
exports.Api = Api;
|
|
8947
9063
|
exports.BRAND_CONTRAST_PAIRS = BRAND_CONTRAST_PAIRS;
|
|
8948
9064
|
exports.BinaryFileRef = BinaryFileRef;
|
|
@@ -1782,6 +1782,48 @@ var onlyOneIntQueryParam = onlyOneStringQueryParam.refine(function (arg) {
|
|
|
1782
1782
|
* this. Shared so client and server agree on the limit.
|
|
1783
1783
|
*/
|
|
1784
1784
|
var JSON_ENTRIES_BATCH_MAX = 100;
|
|
1785
|
+
|
|
1786
|
+
/**
|
|
1787
|
+
* Content analytics, wire format version 1: the beacon the browser script
|
|
1788
|
+
* (`@valbuild/react/analytics`) sends to `POST /api/val/analytics`. Its
|
|
1789
|
+
* `AnalyticsBeacon` type is written by hand there, because that code is on
|
|
1790
|
+
* every visitor's page and must not load zod; `analytics/beacon.test.ts` in
|
|
1791
|
+
* `@valbuild/react` checks that what it builds parses here.
|
|
1792
|
+
*/
|
|
1793
|
+
/*
|
|
1794
|
+
* The limits the browser script keeps to (`MAX_*` in
|
|
1795
|
+
* `@valbuild/react/analytics`'s `beacon.ts`, which cannot import this). The
|
|
1796
|
+
* endpoint takes anyone's POST, so it checks what it is sent rather than
|
|
1797
|
+
* trusting the sender; `beacon.test.ts` builds beacons at the limits and
|
|
1798
|
+
* parses them here.
|
|
1799
|
+
*/
|
|
1800
|
+
var MAX_ANALYTICS_PATHS_PER_BEACON = 200;
|
|
1801
|
+
var AnalyticsPaths = zod.z.record(zod.z.string().max(512), zod.z.array(zod.z.string().max(1024)).max(MAX_ANALYTICS_PATHS_PER_BEACON));
|
|
1802
|
+
var countAnalyticsPaths = function countAnalyticsPaths(paths) {
|
|
1803
|
+
return Object.values(paths).reduce(function (n, list) {
|
|
1804
|
+
return n + list.length;
|
|
1805
|
+
}, 0);
|
|
1806
|
+
};
|
|
1807
|
+
var AnalyticsBeacon = zod.z.object({
|
|
1808
|
+
v: zod.z.literal(1),
|
|
1809
|
+
route: zod.z.string().max(512),
|
|
1810
|
+
cv: zod.z.string().max(128).optional(),
|
|
1811
|
+
view: zod.z.object({
|
|
1812
|
+
ref: zod.z.string().max(253).optional(),
|
|
1813
|
+
utm: zod.z.object({
|
|
1814
|
+
source: zod.z.string().max(100).optional(),
|
|
1815
|
+
medium: zod.z.string().max(100).optional(),
|
|
1816
|
+
campaign: zod.z.string().max(100).optional()
|
|
1817
|
+
}).optional(),
|
|
1818
|
+
device: zod.z["enum"](["phone", "tablet", "desktop"])
|
|
1819
|
+
}).optional(),
|
|
1820
|
+
rendered: AnalyticsPaths,
|
|
1821
|
+
viewed: AnalyticsPaths
|
|
1822
|
+
}).refine(function (beacon) {
|
|
1823
|
+
return countAnalyticsPaths(beacon.rendered) + countAnalyticsPaths(beacon.viewed) <= MAX_ANALYTICS_PATHS_PER_BEACON;
|
|
1824
|
+
}, {
|
|
1825
|
+
message: "At most ".concat(MAX_ANALYTICS_PATHS_PER_BEACON, " paths a beacon")
|
|
1826
|
+
});
|
|
1785
1827
|
var Api = {
|
|
1786
1828
|
"/draft/enable": {
|
|
1787
1829
|
GET: {
|
|
@@ -1827,6 +1869,27 @@ var Api = {
|
|
|
1827
1869
|
})])
|
|
1828
1870
|
}
|
|
1829
1871
|
},
|
|
1872
|
+
"/analytics": {
|
|
1873
|
+
POST: {
|
|
1874
|
+
// Parsed by the handler rather than here, so a beacon of a version this
|
|
1875
|
+
// server does not know is ignored instead of refused.
|
|
1876
|
+
req: {
|
|
1877
|
+
body: zod.z.unknown()
|
|
1878
|
+
},
|
|
1879
|
+
res: zod.z.union([
|
|
1880
|
+
// `counted` is false wherever nothing stores the counts -- every
|
|
1881
|
+
// server but the hosted platform's, for now.
|
|
1882
|
+
zod.z.object({
|
|
1883
|
+
status: zod.z.literal(200),
|
|
1884
|
+
json: zod.z.object({
|
|
1885
|
+
counted: zod.z["boolean"]()
|
|
1886
|
+
})
|
|
1887
|
+
}), zod.z.object({
|
|
1888
|
+
status: zod.z.literal(400),
|
|
1889
|
+
json: GenericError
|
|
1890
|
+
})])
|
|
1891
|
+
}
|
|
1892
|
+
},
|
|
1830
1893
|
"/draft/stat": {
|
|
1831
1894
|
GET: {
|
|
1832
1895
|
req: {
|
|
@@ -4093,6 +4156,58 @@ function isRetryable(error) {
|
|
|
4093
4156
|
* modules. See `docs/plans/demo-mode.md`.
|
|
4094
4157
|
*/
|
|
4095
4158
|
|
|
4159
|
+
/**
|
|
4160
|
+
* What the site starts the demo with: `<ValApp demo={{ tour }}>`.
|
|
4161
|
+
*
|
|
4162
|
+
* `demo` alone (`true`) is the same with nothing given.
|
|
4163
|
+
*/
|
|
4164
|
+
|
|
4165
|
+
/** One item of the demo script. */
|
|
4166
|
+
|
|
4167
|
+
/**
|
|
4168
|
+
* An answer to "What brings you here?".
|
|
4169
|
+
*
|
|
4170
|
+
* The first tour of its list is the one the card offers first, with a
|
|
4171
|
+
* button of its own: the one to start with.
|
|
4172
|
+
*/
|
|
4173
|
+
|
|
4174
|
+
/**
|
|
4175
|
+
* A control of the Studio's a step can point at.
|
|
4176
|
+
*
|
|
4177
|
+
* The `data-val-tour` markers the Studio puts on them. One that is not on
|
|
4178
|
+
* screen (the rail on a phone) leaves the card on its own, so a step's words
|
|
4179
|
+
* must work without the arrow: never "this button here".
|
|
4180
|
+
*/
|
|
4181
|
+
|
|
4182
|
+
/** A panel a step opens, so what it is about is on screen behind the card. */
|
|
4183
|
+
|
|
4184
|
+
/**
|
|
4185
|
+
* What moves a step on by itself. A step without one has Next.
|
|
4186
|
+
*
|
|
4187
|
+
* Each is something the visitor does, because doing it is the lesson, and
|
|
4188
|
+
* each has a "Do it for me" that does it the way the Studio would:
|
|
4189
|
+
*
|
|
4190
|
+
* - `open`: a field at or below this source path is opened -- by clicking it
|
|
4191
|
+
* on the page, or anywhere else. Do it for me opens it.
|
|
4192
|
+
* - `edit`: a change is made. Do it for me writes `value` at `path` --
|
|
4193
|
+
* replacing what is there, or with `add: true` adding it, as a new entry of
|
|
4194
|
+
* a record or a new item of a list at that index; without them, it is
|
|
4195
|
+
* offered nowhere and the step waits for the visitor.
|
|
4196
|
+
* - `newPage`: a page is added. Do it for me adds the page this source path
|
|
4197
|
+
* names (a page router's module and the new page's key, `?p="/journal/x"`)
|
|
4198
|
+
* the way the New page form does, empty, and opens it.
|
|
4199
|
+
* - `panel`: that panel is opened. Do it for me opens it.
|
|
4200
|
+
* - `locale`: the language shown is changed. Do it for me picks the next one.
|
|
4201
|
+
*/
|
|
4202
|
+
|
|
4203
|
+
/**
|
|
4204
|
+
* One stop of the demo's tour, as the site writes it.
|
|
4205
|
+
*
|
|
4206
|
+
* Data rather than components, so the tour can be rewritten -- and tried on
|
|
4207
|
+
* people -- without a Val release: the Studio draws it, the site says what it
|
|
4208
|
+
* says. Written for someone who has never seen Val.
|
|
4209
|
+
*/
|
|
4210
|
+
|
|
4096
4211
|
/*
|
|
4097
4212
|
* A global `var` rather than a `Window` member: this package is compiled
|
|
4098
4213
|
* without the DOM's types, and a `var` in global scope is also a property of
|
|
@@ -8943,6 +9058,7 @@ exports.parseRoutePattern = getSitemapTree.parseRoutePattern;
|
|
|
8943
9058
|
exports.withValCanvasParam = getSitemapTree.withValCanvasParam;
|
|
8944
9059
|
exports.AA_LARGE = AA_LARGE;
|
|
8945
9060
|
exports.AA_TEXT = AA_TEXT;
|
|
9061
|
+
exports.AnalyticsBeacon = AnalyticsBeacon;
|
|
8946
9062
|
exports.Api = Api;
|
|
8947
9063
|
exports.BRAND_CONTRAST_PAIRS = BRAND_CONTRAST_PAIRS;
|
|
8948
9064
|
exports.BinaryFileRef = BinaryFileRef;
|
|
@@ -1775,6 +1775,48 @@ var onlyOneIntQueryParam = onlyOneStringQueryParam.refine(function (arg) {
|
|
|
1775
1775
|
* this. Shared so client and server agree on the limit.
|
|
1776
1776
|
*/
|
|
1777
1777
|
var JSON_ENTRIES_BATCH_MAX = 100;
|
|
1778
|
+
|
|
1779
|
+
/**
|
|
1780
|
+
* Content analytics, wire format version 1: the beacon the browser script
|
|
1781
|
+
* (`@valbuild/react/analytics`) sends to `POST /api/val/analytics`. Its
|
|
1782
|
+
* `AnalyticsBeacon` type is written by hand there, because that code is on
|
|
1783
|
+
* every visitor's page and must not load zod; `analytics/beacon.test.ts` in
|
|
1784
|
+
* `@valbuild/react` checks that what it builds parses here.
|
|
1785
|
+
*/
|
|
1786
|
+
/*
|
|
1787
|
+
* The limits the browser script keeps to (`MAX_*` in
|
|
1788
|
+
* `@valbuild/react/analytics`'s `beacon.ts`, which cannot import this). The
|
|
1789
|
+
* endpoint takes anyone's POST, so it checks what it is sent rather than
|
|
1790
|
+
* trusting the sender; `beacon.test.ts` builds beacons at the limits and
|
|
1791
|
+
* parses them here.
|
|
1792
|
+
*/
|
|
1793
|
+
var MAX_ANALYTICS_PATHS_PER_BEACON = 200;
|
|
1794
|
+
var AnalyticsPaths = z.record(z.string().max(512), z.array(z.string().max(1024)).max(MAX_ANALYTICS_PATHS_PER_BEACON));
|
|
1795
|
+
var countAnalyticsPaths = function countAnalyticsPaths(paths) {
|
|
1796
|
+
return Object.values(paths).reduce(function (n, list) {
|
|
1797
|
+
return n + list.length;
|
|
1798
|
+
}, 0);
|
|
1799
|
+
};
|
|
1800
|
+
var AnalyticsBeacon = z.object({
|
|
1801
|
+
v: z.literal(1),
|
|
1802
|
+
route: z.string().max(512),
|
|
1803
|
+
cv: z.string().max(128).optional(),
|
|
1804
|
+
view: z.object({
|
|
1805
|
+
ref: z.string().max(253).optional(),
|
|
1806
|
+
utm: z.object({
|
|
1807
|
+
source: z.string().max(100).optional(),
|
|
1808
|
+
medium: z.string().max(100).optional(),
|
|
1809
|
+
campaign: z.string().max(100).optional()
|
|
1810
|
+
}).optional(),
|
|
1811
|
+
device: z["enum"](["phone", "tablet", "desktop"])
|
|
1812
|
+
}).optional(),
|
|
1813
|
+
rendered: AnalyticsPaths,
|
|
1814
|
+
viewed: AnalyticsPaths
|
|
1815
|
+
}).refine(function (beacon) {
|
|
1816
|
+
return countAnalyticsPaths(beacon.rendered) + countAnalyticsPaths(beacon.viewed) <= MAX_ANALYTICS_PATHS_PER_BEACON;
|
|
1817
|
+
}, {
|
|
1818
|
+
message: "At most ".concat(MAX_ANALYTICS_PATHS_PER_BEACON, " paths a beacon")
|
|
1819
|
+
});
|
|
1778
1820
|
var Api = {
|
|
1779
1821
|
"/draft/enable": {
|
|
1780
1822
|
GET: {
|
|
@@ -1820,6 +1862,27 @@ var Api = {
|
|
|
1820
1862
|
})])
|
|
1821
1863
|
}
|
|
1822
1864
|
},
|
|
1865
|
+
"/analytics": {
|
|
1866
|
+
POST: {
|
|
1867
|
+
// Parsed by the handler rather than here, so a beacon of a version this
|
|
1868
|
+
// server does not know is ignored instead of refused.
|
|
1869
|
+
req: {
|
|
1870
|
+
body: z.unknown()
|
|
1871
|
+
},
|
|
1872
|
+
res: z.union([
|
|
1873
|
+
// `counted` is false wherever nothing stores the counts -- every
|
|
1874
|
+
// server but the hosted platform's, for now.
|
|
1875
|
+
z.object({
|
|
1876
|
+
status: z.literal(200),
|
|
1877
|
+
json: z.object({
|
|
1878
|
+
counted: z["boolean"]()
|
|
1879
|
+
})
|
|
1880
|
+
}), z.object({
|
|
1881
|
+
status: z.literal(400),
|
|
1882
|
+
json: GenericError
|
|
1883
|
+
})])
|
|
1884
|
+
}
|
|
1885
|
+
},
|
|
1823
1886
|
"/draft/stat": {
|
|
1824
1887
|
GET: {
|
|
1825
1888
|
req: {
|
|
@@ -4086,6 +4149,58 @@ function isRetryable(error) {
|
|
|
4086
4149
|
* modules. See `docs/plans/demo-mode.md`.
|
|
4087
4150
|
*/
|
|
4088
4151
|
|
|
4152
|
+
/**
|
|
4153
|
+
* What the site starts the demo with: `<ValApp demo={{ tour }}>`.
|
|
4154
|
+
*
|
|
4155
|
+
* `demo` alone (`true`) is the same with nothing given.
|
|
4156
|
+
*/
|
|
4157
|
+
|
|
4158
|
+
/** One item of the demo script. */
|
|
4159
|
+
|
|
4160
|
+
/**
|
|
4161
|
+
* An answer to "What brings you here?".
|
|
4162
|
+
*
|
|
4163
|
+
* The first tour of its list is the one the card offers first, with a
|
|
4164
|
+
* button of its own: the one to start with.
|
|
4165
|
+
*/
|
|
4166
|
+
|
|
4167
|
+
/**
|
|
4168
|
+
* A control of the Studio's a step can point at.
|
|
4169
|
+
*
|
|
4170
|
+
* The `data-val-tour` markers the Studio puts on them. One that is not on
|
|
4171
|
+
* screen (the rail on a phone) leaves the card on its own, so a step's words
|
|
4172
|
+
* must work without the arrow: never "this button here".
|
|
4173
|
+
*/
|
|
4174
|
+
|
|
4175
|
+
/** A panel a step opens, so what it is about is on screen behind the card. */
|
|
4176
|
+
|
|
4177
|
+
/**
|
|
4178
|
+
* What moves a step on by itself. A step without one has Next.
|
|
4179
|
+
*
|
|
4180
|
+
* Each is something the visitor does, because doing it is the lesson, and
|
|
4181
|
+
* each has a "Do it for me" that does it the way the Studio would:
|
|
4182
|
+
*
|
|
4183
|
+
* - `open`: a field at or below this source path is opened -- by clicking it
|
|
4184
|
+
* on the page, or anywhere else. Do it for me opens it.
|
|
4185
|
+
* - `edit`: a change is made. Do it for me writes `value` at `path` --
|
|
4186
|
+
* replacing what is there, or with `add: true` adding it, as a new entry of
|
|
4187
|
+
* a record or a new item of a list at that index; without them, it is
|
|
4188
|
+
* offered nowhere and the step waits for the visitor.
|
|
4189
|
+
* - `newPage`: a page is added. Do it for me adds the page this source path
|
|
4190
|
+
* names (a page router's module and the new page's key, `?p="/journal/x"`)
|
|
4191
|
+
* the way the New page form does, empty, and opens it.
|
|
4192
|
+
* - `panel`: that panel is opened. Do it for me opens it.
|
|
4193
|
+
* - `locale`: the language shown is changed. Do it for me picks the next one.
|
|
4194
|
+
*/
|
|
4195
|
+
|
|
4196
|
+
/**
|
|
4197
|
+
* One stop of the demo's tour, as the site writes it.
|
|
4198
|
+
*
|
|
4199
|
+
* Data rather than components, so the tour can be rewritten -- and tried on
|
|
4200
|
+
* people -- without a Val release: the Studio draws it, the site says what it
|
|
4201
|
+
* says. Written for someone who has never seen Val.
|
|
4202
|
+
*/
|
|
4203
|
+
|
|
4089
4204
|
/*
|
|
4090
4205
|
* A global `var` rather than a `Window` member: this package is compiled
|
|
4091
4206
|
* without the DOM's types, and a `var` in global scope is also a property of
|
|
@@ -8915,4 +9030,4 @@ function schemaErrorsOf(schema, moduleFilePath, source) {
|
|
|
8915
9030
|
return errors;
|
|
8916
9031
|
}
|
|
8917
9032
|
|
|
8918
|
-
export { AA_LARGE, AA_TEXT, Api, BRAND_CONTRAST_PAIRS, BinaryFileRef, CodeOptions, ColorOptions, DEFAULT_ERROR_MESSAGE, DateOptions, ENCODE_DEFAULTS, ENCODE_MIME_TYPE_OF, FileOptions, HistoricalCommit, HistoricalModule, HistoricalPatchSet, HistoryError, ImageEncodeOption, ImageOptions, JSONValue, JSON_ENTRIES_BATCH_MAX, ModuleComparison, NEVER_ENCODED, ParentRef$1 as ParentRef, Patch, PatchBlock, PatchId, PatchJSON, PatchSets, PlanRefusalError, PublishProtocolError, RAMP_STEPS, RemirrorBr, RemirrorBulletList, RemirrorHeading, RemirrorImage, RemirrorJSON, RemirrorLinkMark, RemirrorListItem, RemirrorOrderedList, RemirrorParagraph, RemirrorText, RemirrorTextMark, RestoreVerdict, RichTextOptions, SCHEMA_SOURCE_FIXES, STUDIO_FIXES, SerializedArraySchema, SerializedBooleanSchema, SerializedCodeSchema, SerializedColorSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedFileSchema, SerializedImageSchema, SerializedKeyOfSchema, SerializedLiteralSchema, SerializedLocaleSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedRecordSchema, SerializedRichTextSchema, SerializedRouteSchema, SerializedSchema, SerializedSettingsSchema, SerializedStringSchema, SerializedValViewSchema, SerializedVideoSchema, SharedValConfig, VAL_ENABLE_COOKIE_NAME, VAL_GREEN_RAMP, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, VAL_STUDIO_HEADER, ValCommit, ValDeployment, VideoOptions, VideoStreamOption, WASM_ENCODED_MIME_TYPES, accentRamp, buildDuplicatePatch, buildEmptyAtPathPatch, buildFileRefValue, buildImageGalleryPatch, buildRemoveImageGalleryEntryPatch, buildSearchIndex, chainHeadOf, checkCompatibility, chooseEncoded, concatModulePath, contrastRatio, createRegExpFromPattern, createSearchIndex, createValClient, declaredLocales, describeContainerAtPath, emptyOf, enumLocaleTag, explainIncompatible, fallbackMimeType, filterBlockingValidationErrors, filterRoutesByPatterns, findSimilar, fitWithin, flattenRichText, forEachRichTextImage, getErrorMessageFromUnknownJson, getFilenameFromRef, getInlineImgInfo, getKeyOfRecordAt, getRefParts, getRoutesOf, getRoutesWithModulePaths, getSourceAt, getValDemo, indexModule, isInsidePatchSetPath, isLocaleSchema, isMimeTypeAccepted, isRemoteSchema, isRepairedOnSave, isSchemaSourceFixError, isSkippedSource, isStudioFix, joinSharedChanges, keyOfRecordPath, levenshtein, localeAt, localeMeantBy, memoizePerRequest, newestCommitSha, parseArtifacts, parseBuildTarget, parseCancel, parseDeclare, parseDiscard, parseJob, parseNewestCiRun, parsePress, parseProblems, parseProjectSource, parsePromote, parsePublishToken, parseRenew, parseRequestStatus, parseStatus, parseUpdateTarget, parseVerify, partitionValidationErrors, performSearch, relativeLuminance, remirrorToRichTextSource, removeModule, resolveEncodeSettings, resolvePairGround, resolveSchemaSourceFixForError, resolveSchemaSourceFixes, resolveSerializedSchemaAtPath, richTextImageSchema, richTextToRemirror, safeParsePatch, schemaErrorsOf, schemaTypesOfPath, selectionClosure, shouldEncodeWithWasm, sideFiles, sideSource, sourcePathOfChild, themeCustomProperties, toolNames, traverseSchemaSource, urlOf, validateRoutePatterns, withExtension };
|
|
9033
|
+
export { AA_LARGE, AA_TEXT, AnalyticsBeacon, Api, BRAND_CONTRAST_PAIRS, BinaryFileRef, CodeOptions, ColorOptions, DEFAULT_ERROR_MESSAGE, DateOptions, ENCODE_DEFAULTS, ENCODE_MIME_TYPE_OF, FileOptions, HistoricalCommit, HistoricalModule, HistoricalPatchSet, HistoryError, ImageEncodeOption, ImageOptions, JSONValue, JSON_ENTRIES_BATCH_MAX, ModuleComparison, NEVER_ENCODED, ParentRef$1 as ParentRef, Patch, PatchBlock, PatchId, PatchJSON, PatchSets, PlanRefusalError, PublishProtocolError, RAMP_STEPS, RemirrorBr, RemirrorBulletList, RemirrorHeading, RemirrorImage, RemirrorJSON, RemirrorLinkMark, RemirrorListItem, RemirrorOrderedList, RemirrorParagraph, RemirrorText, RemirrorTextMark, RestoreVerdict, RichTextOptions, SCHEMA_SOURCE_FIXES, STUDIO_FIXES, SerializedArraySchema, SerializedBooleanSchema, SerializedCodeSchema, SerializedColorSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedFileSchema, SerializedImageSchema, SerializedKeyOfSchema, SerializedLiteralSchema, SerializedLocaleSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedRecordSchema, SerializedRichTextSchema, SerializedRouteSchema, SerializedSchema, SerializedSettingsSchema, SerializedStringSchema, SerializedValViewSchema, SerializedVideoSchema, SharedValConfig, VAL_ENABLE_COOKIE_NAME, VAL_GREEN_RAMP, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, VAL_STUDIO_HEADER, ValCommit, ValDeployment, VideoOptions, VideoStreamOption, WASM_ENCODED_MIME_TYPES, accentRamp, buildDuplicatePatch, buildEmptyAtPathPatch, buildFileRefValue, buildImageGalleryPatch, buildRemoveImageGalleryEntryPatch, buildSearchIndex, chainHeadOf, checkCompatibility, chooseEncoded, concatModulePath, contrastRatio, createRegExpFromPattern, createSearchIndex, createValClient, declaredLocales, describeContainerAtPath, emptyOf, enumLocaleTag, explainIncompatible, fallbackMimeType, filterBlockingValidationErrors, filterRoutesByPatterns, findSimilar, fitWithin, flattenRichText, forEachRichTextImage, getErrorMessageFromUnknownJson, getFilenameFromRef, getInlineImgInfo, getKeyOfRecordAt, getRefParts, getRoutesOf, getRoutesWithModulePaths, getSourceAt, getValDemo, indexModule, isInsidePatchSetPath, isLocaleSchema, isMimeTypeAccepted, isRemoteSchema, isRepairedOnSave, isSchemaSourceFixError, isSkippedSource, isStudioFix, joinSharedChanges, keyOfRecordPath, levenshtein, localeAt, localeMeantBy, memoizePerRequest, newestCommitSha, parseArtifacts, parseBuildTarget, parseCancel, parseDeclare, parseDiscard, parseJob, parseNewestCiRun, parsePress, parseProblems, parseProjectSource, parsePromote, parsePublishToken, parseRenew, parseRequestStatus, parseStatus, parseUpdateTarget, parseVerify, partitionValidationErrors, performSearch, relativeLuminance, remirrorToRichTextSource, removeModule, resolveEncodeSettings, resolvePairGround, resolveSchemaSourceFixForError, resolveSchemaSourceFixes, resolveSerializedSchemaAtPath, richTextImageSchema, richTextToRemirror, safeParsePatch, schemaErrorsOf, schemaTypesOfPath, selectionClosure, shouldEncodeWithWasm, sideFiles, sideSource, sourcePathOfChild, themeCustomProperties, toolNames, traverseSchemaSource, urlOf, validateRoutePatterns, withExtension };
|