Commit 42f8c73
authored
feat(scripts): one Sieve generator, and the preview now comes from it (#61)
* feat(scripts): one Sieve generator, and the preview now comes from it
`previewRule` in scriptDocument.js was a second implementation of
SieveGenerator. Both modules said so in a comment — "it is a second
implementation of the backend generator and the two must agree",
"it must agree with the backend generator" — and nothing checked it.
Five divergences had shipped:
1. dropped `negate`, so a NOT condition previewed as its opposite
2. no quote escaping
3. a disabled rule shown live, with no ## anywhere
4. no `# --- name ---` line, the only place a Rule's name is stored
5. NOTHING at all for a Rule whose last Condition was deleted, while
a save writes `if anyof ( ) {` — Sieve a real server refuses
The fifth is the worst: the editor showed an empty preview for the one
state where the user most needed to be told something was wrong.
POST /api/scripts/preview renders one Rule and answers. It depends on
get_session and NOT on get_script_store, so it authenticates without
opening a ManageSieve connection — the editor calls it on a keystroke
timer, and a connection per keystroke is a denial of service aimed at
the user's own mail server. That guard is a test, and the test is
mutation-checked: swapping the dependency makes it fail, and a second
test proves the sabotage bites on a route that DOES take the store.
Save and preview now go through one function. `generate` used to inline
the `## `-prefixing for a disabled Rule; that is `SieveGenerator
.generate_entry` now, and both callers use it. `generate_rule` and
`rule_from_json` are the module-level rule-sized entry points.
THE TEST THAT COULD NOT EXIST BEFORE: preview a Rule, save that same
Rule, and require the preview to be a literal substring of what the
store then holds — across nine shapes including all five divergences.
An agreement test needs one side to be authoritative; there was no such
side while there were two generators.
previewRule, renderTest, renderAction and the frontend `quote` are
deleted, with their 93 lines of tests. Deleting the duplicate beats
testing it. In their place scriptDocument exports `entryToWire`, which
`toWire` now maps over — the preview must post the SAME projection a
save posts, or it is previewing something else again.
The editor debounces at 200ms and carries a sequence number, so a slow
answer for an older Rule cannot overwrite a newer one, and it says
"preview unavailable" rather than leaving the previous rule's Sieve on
screen next to the rule being edited.
Route inventory updated in both of its lists. A script may still be
CALLED "preview" — pinned, because `POST /{name}` does not exist today
and the day it does the shadowing would be silent.
1017 backend tests, 54 frontend, svelte-check 0/0, ruff clean.
Refs areyousievious-8fg.17
* style(frontend): the blank lines the review counted
Cosmetic only — doubled blank lines either side of the entryToWire block.
Refs areyousievious-8fg.17
* perf(frontend): preview only when the selected rule actually changed
Raised in review of #61, and my comment was the weaker claim: it said the
trigger fires on each keystroke, when it fires on ANY document mutation.
`rules` is rebuilt whenever `script` is reassigned, so adding, deleting or
reordering some OTHER rule rescheduled a preview of the selected one and
spent a request to be told the same bytes it was already showing.
Comparing the wire payload rather than the array reference makes those
free, and covers the keystroke that leaves wire content unchanged too. The
payload compared is the one that gets posted, so the two cannot drift.
An error clears the remembered payload, so the next mutation retries
rather than matching it and leaving the message up for good.
The comment now says what actually happens.
Not unit-tested: the logic is inside a .svelte file and this repo has no
component test harness. svelte-check, vitest and the build are clean.
Refs areyousievious-8fg.171 parent 0f7037d commit 42f8c73
16 files changed
Lines changed: 691 additions & 218 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
| 23 | + | |
22 | 24 | | |
23 | 25 | | |
24 | 26 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
| 33 | + | |
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
179 | 179 | | |
180 | 180 | | |
181 | 181 | | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
182 | 195 | | |
183 | 196 | | |
184 | 197 | | |
| |||
224 | 237 | | |
225 | 238 | | |
226 | 239 | | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
7 | 12 | | |
8 | 13 | | |
9 | 14 | | |
| |||
15 | 20 | | |
16 | 21 | | |
17 | 22 | | |
| 23 | + | |
| 24 | + | |
18 | 25 | | |
19 | 26 | | |
20 | 27 | | |
21 | 28 | | |
22 | 29 | | |
23 | 30 | | |
| 31 | + | |
24 | 32 | | |
25 | | - | |
| 33 | + | |
26 | 34 | | |
27 | 35 | | |
28 | 36 | | |
| 37 | + | |
29 | 38 | | |
30 | 39 | | |
31 | 40 | | |
| 41 | + | |
32 | 42 | | |
33 | 43 | | |
34 | 44 | | |
| |||
90 | 100 | | |
91 | 101 | | |
92 | 102 | | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
93 | 120 | | |
94 | 121 | | |
95 | 122 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
486 | 486 | | |
487 | 487 | | |
488 | 488 | | |
489 | | - | |
490 | | - | |
491 | | - | |
492 | | - | |
493 | | - | |
494 | | - | |
| 489 | + | |
495 | 490 | | |
496 | 491 | | |
497 | 492 | | |
| |||
501 | 496 | | |
502 | 497 | | |
503 | 498 | | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
504 | 518 | | |
505 | 519 | | |
506 | 520 | | |
| |||
704 | 718 | | |
705 | 719 | | |
706 | 720 | | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
0 commit comments