@valbuild/shared 0.120.0 → 0.122.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/CHANGELOG.md CHANGED
@@ -1,5 +1,189 @@
1
1
  # @valbuild/shared
2
2
 
3
+ ## 0.122.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#563](https://github.com/valbuild/val/pull/563) [`be32261`](https://github.com/valbuild/val/commit/be32261af19db8018bc37b180d903416018c0b79) Thanks [@freekh](https://github.com/freekh)! - See how a module looked at any past commit, and restore from it by pointing at it
8
+
9
+ Val could publish edits but never look back. Now every commit is a durable
10
+ record you can open, and any part of it can be put back.
11
+
12
+ **Open a commit and the Studio splits in two.** The left half is the Studio
13
+ itself — same navigation, same fields, same everything, because it _is_ the
14
+ editor rather than a copy of it. The right half shows the project as that commit
15
+ left it. On a phone the two become one pane and a toggle.
16
+
17
+ **Restoring is directed: you point at the old value, then at where it goes.**
18
+ Val does not try to work out which of today's fields corresponds to which of the
19
+ commit's. It cannot be sure — array items splice, schemas move — and a restore
20
+ that guesses wrong writes into the wrong place and looks like it worked. Two
21
+ picks leave nothing to guess. You can restore across paths, so last month's
22
+ headline can become today's tagline.
23
+
24
+ Before you click, every field on the "now" side says whether it can hold the
25
+ value you picked, and a field that cannot explains why when you click it rather
26
+ than doing nothing. A changed union is not itself a blocker: what matters is
27
+ whether the value's own shape is still allowed, so a union that gained a case
28
+ restores fine and one that lost the case you are restoring does not.
29
+
30
+ Rich text can be restored but is marked "probably fits" rather than confirmed —
31
+ comparing every mark and block against the options a schema allows is not done
32
+ yet, and saying so is better than a confident answer we cannot back. It is
33
+ checked properly the moment you commit to it: before anything is staged, the old
34
+ value is checked against the field it is going into, and a value that cannot be
35
+ that field is refused with the reason. A value that is the right shape but
36
+ breaks a rule about its content — a name too short for its `minLength` — is
37
+ staged and then held at publish, the same as if you had typed it, because a
38
+ restore should not be stricter than typing.
39
+
40
+ **A whole module can be put back on its own**, from a commit that changed
41
+ several, without reverting the rest of the commit.
42
+
43
+ **Restores are staged, not applied.** They land in pending changes, are reviewed
44
+ beside every other edit, and go out with the next publish. There is also "put
45
+ everything back", for when a whole publish was the mistake.
46
+
47
+ To make this possible, publishing now records each changed module's data and the
48
+ schema it was written against. Not the `.val.ts` — git already keeps that, but
49
+ it is code, and turning code back into data means parsing it, which is
50
+ best-effort and stops working as TypeScript, your runtime and Val move on. The
51
+ schema is kept because a value on its own cannot be drawn: showing a module as it
52
+ was at a commit whose schema has since changed needs _that commit's_ schema, and
53
+ nothing in your current checkout has it.
54
+
55
+ Things it will not pretend about: a module the commit did not touch says so
56
+ rather than showing today's value; a module saved by a different version of Val
57
+ says the version differs and that nothing is lost; a commit made before Val
58
+ started recording history disables restore with the reason next to it. Images
59
+ and files are restored by re-uploading them, since the bytes at an old commit
60
+ may no longer be on your branch.
61
+
62
+ History requires the Val content service. In filesystem mode it reports
63
+ `not-supported-in-fs-mode` rather than faking it from git, which has the files
64
+ but not which of a commit's changes were one editor's work.
65
+
66
+ ### Patch Changes
67
+
68
+ - [#618](https://github.com/valbuild/val/pull/618) [`da6794f`](https://github.com/valbuild/val/commit/da6794f3dbd77d49ccfe780b359bab1689ee1b11) Thanks [@freekh](https://github.com/freekh)! - Remove the unused `GET /api/val/session` endpoint.
69
+
70
+ Nothing called it. The Studio reads the profile id from `/stat`, and in proxy
71
+ mode the route proxied to `${VAL_BUILD_URL}/api/val/${project}/auth/session`,
72
+ an upstream route that no longer exists — so calling it by hand returned a 500
73
+ rather than a session. It is gone from both the route declarations in
74
+ `@valbuild/shared` and the implementation in `@valbuild/server`.
75
+
76
+ Session cookie handling itself is unchanged: `/authorize`, `/callback` and
77
+ `/logout` still set and clear `val_session` as before.
78
+
79
+ ## 0.121.0
80
+
81
+ ### Minor Changes
82
+
83
+ - [#464](https://github.com/valbuild/val/pull/464) [`2bcc6fd`](https://github.com/valbuild/val/commit/2bcc6fdff8d668123e07e3c5e81ac6fa1436e47b) Thanks [@freekh](https://github.com/freekh)! - Add staging and unstaging of pending changes, so one person can publish a small fix without shipping somebody else's unfinished work.
84
+
85
+ A **patch group** is the set of patches one user has chosen to publish. It is not a patch _set_: a patch set is computed from the schema and says which patches must move together, while a patch group is curated and says which ones you want live.
86
+
87
+ A group holds its owner's own work plus whatever the closure entangled with it — not everything pending. **So Publish changes meaning on a shared branch: it ships your changes and what they depend on, instead of everything anybody has pending.** That is the feature. Unstaging goes further: hold one of your own changes back and it leaves both your preview and your publish, while still existing for everyone else.
88
+
89
+ The rule relating the two is that for every group and every patch set, the group's members within that patch set must form a prefix in patch-chain order. Staging a change therefore pulls in whatever preceded it in the same patch set; unstaging drops whatever was built on top of it. The compare view names what a toggle moves, and whose it is, rather than quietly enlarging or shrinking a publish.
90
+
91
+ Editing inside a region you are holding back is allowed, and the patches you were holding are loaded back in rather than the edit being refused. An earlier design made such a region read-only until it was staged again, because an author picks an array index while looking at their own view — so re-staging patches afterwards can shift the content under the path they just chose, and their edit lands on the wrong element cleanly, with every invariant intact and only the content wrong. That guard is not what ships. It is a rare shape in practice, since two people's edits mostly land in different routes, and refusing an edit for a reason the author cannot see is a worse everyday experience than the case it prevents. Instead the real result is shown immediately: the widened set is what the editor renders and what the compare view lists.
92
+
93
+ Also fixes a pre-existing bug in patch set grouping: patch set paths were compared with a raw string prefix test, and nothing terminates a path segment, so `?foobar/title` matched `?foo`. Deleting record key `foo` and retitling record key `foobar` were treated as one inseparable change. Previously that over-grouped two unrelated edits in the review screen; with staging it would have meant publishing a deletion nobody asked for.
94
+
95
+ The `/patches` routes gain optional patch group fields and `/patch-groups/~/patches` is new. This needs a content API that has patch groups. Filesystem mode keeps the group in the client, since it has a single author and already sends an explicit patch id list when publishing.
96
+
97
+ When a save pulls other people's changes in, you are told: a toast names how many and whose. There is no undo, because your edit was written against the view those changes produce and now depends on them — the compare view shows the widened set.
98
+
99
+ Two other things keep a session honest about a shared branch. `/stat` now says which pending changes have already been published, so another author's publish stops looking pending in your Studio the moment it lands rather than when the site redeploys. And Publish refuses, without writing anything, if somebody published while you were reviewing — the review screen you acted on described a branch that has since moved.
100
+
101
+ Two things this does **not** do yet, both of which need the group annotation to refresh on its own rather than only inside a fetch for missing patch ids:
102
+
103
+ - a stage or unstage in one tab does not reach another tab;
104
+ - if persisting a stage fails, the local view keeps it until the page is reloaded.
105
+
106
+ `docs/independent-publish/DESIGN.md` describes the model and lists what is still a judgement call.
107
+
108
+ - [#605](https://github.com/valbuild/val/pull/605) [`6794d29`](https://github.com/valbuild/val/commit/6794d2980bc81284ab7f2cc667f01cc21c9e3a79) Thanks [@freekh](https://github.com/freekh)! - `s.settings()`: the project's settings, as content.
109
+
110
+ A settings module is one per project, at the root of the content tree:
111
+
112
+ ```typescript
113
+ // settings.val.ts
114
+ export default c.define("/settings.val.ts", s.settings(), {});
115
+ ```
116
+
117
+ Register it in `val.modules.ts` like any other module, and it shows up in the
118
+ Studio under the cog at the foot of the left rail. Everything in it is content:
119
+ it is edited as a draft, it appears in the publish diff, and it is the same for
120
+ everyone working on the project.
121
+
122
+ Every key is optional, at every level, so `{}` is a complete settings module —
123
+ and stays one as sections are added. What it holds today is the assistant:
124
+
125
+ ```typescript
126
+ export default c.define("/settings.val.ts", s.settings(), {
127
+ assistant: {
128
+ enabled: true,
129
+ context: "A CMS for developers, run by a team of four in Oslo.",
130
+ tone: "Plain and direct. British English, sentence case in headings.",
131
+ },
132
+ });
133
+ ```
134
+
135
+ `context` is background the assistant would otherwise guess at; `tone` is how it
136
+ should write when it writes content. Both are sent with every message it makes.
137
+
138
+ `enabled` decides whether editors have an assistant, and it has **three** states
139
+ rather than two:
140
+
141
+ - `true` — they do.
142
+ - `false` — they do not, and every trace of it goes: no button in the top bar,
143
+ no row in the quick actions, no panel, nothing sent.
144
+ - unset — nobody has decided. The assistant is still **shown**, and asks to be
145
+ turned on before it is used. Hiding an assistant nobody has decided about
146
+ means nobody discovers it; quietly enabling one means a project starts sending
147
+ its content to a model because it did not know to say no.
148
+
149
+ A project with no settings module at all has an assistant, as before: there is
150
+ nowhere to record a decision, and nowhere for the prompt to write the answer.
151
+
152
+ **Breaking: `ai.chat` is gone from `val.config.ts`.** Whether the assistant is
153
+ available is a decision about the project's content, made by the people who edit
154
+ it, so it moved to settings — turning the chat on used to take a developer, a
155
+ deploy and a code review of a boolean. Remove the whole block:
156
+
157
+ ```diff
158
+ const { s, c, val, config } = initVal({
159
+ - ai: {
160
+ - chat: {
161
+ - experimental: { enable: true },
162
+ - suggestions: ["Summarize", "Fix typos at this page"],
163
+ - title: "Ask me anything",
164
+ - description: "Val can answer questions about the content.",
165
+ - },
166
+ - },
167
+ });
168
+ ```
169
+
170
+ `experimental.enable` becomes `assistant.enabled` in the settings module.
171
+ `suggestions`, `title` and `description` are removed with nothing replacing
172
+ them: the assistant now opens with its own copy. A project that had the chat
173
+ enabled and wants it to stay on for everyone should write
174
+ `assistant: { enabled: true }` — otherwise editors are offered it and asked.
175
+
176
+ `ai.commitMessages` stays in `val.config.ts`, and is unaffected.
177
+
178
+ Two settings modules, or one in a subdirectory, is a module error: the dev
179
+ server refuses to serve sources, `npx val validate` reports it against the file,
180
+ and the Studio says so rather than picking one.
181
+
182
+ ### Patch Changes
183
+
184
+ - Updated dependencies [[`2bcbee1`](https://github.com/valbuild/val/commit/2bcbee1be682c2bbd5b7bc7d152ddd4204162fd2), [`6794d29`](https://github.com/valbuild/val/commit/6794d2980bc81284ab7f2cc667f01cc21c9e3a79)]:
185
+ - @valbuild/core@0.121.0
186
+
3
187
  ## 0.120.0
4
188
 
5
189
  ### Minor Changes