@valbuild/server 0.136.9 → 0.137.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,86 @@
1
1
  # @valbuild/server
2
2
 
3
+ ## 0.137.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#676](https://github.com/valbuild/val/pull/676) [`48ac9f0`](https://github.com/valbuild/val/commit/48ac9f06dd59a5b4ca60232b1ef198cf42f23aa6) Thanks [@freekh](https://github.com/freekh)! - A link-check endpoint, so the Studio can find out whether an external page is
8
+ still there.
9
+
10
+ `POST /external-urls/check` opens up to twenty URLs and reports what answered:
11
+ the final status after redirects, where it ended up, and how long it took. The
12
+ Studio's Check button in the external pages dialog is the only caller, and it
13
+ cannot do this itself — a cross-origin `fetch` from a browser cannot read a
14
+ response status without CORS headers no ordinary site sends.
15
+
16
+ It is an endpoint that makes outbound requests to addresses your content
17
+ supplies, so it is built as one:
18
+
19
+ - It is behind the same session check as every other authenticated route —
20
+ which, in fs mode, means the same anonymous access every other route allows
21
+ on a developer's own machine. It is not a new way in; it is the same door.
22
+ - It refuses to connect to anything that is not a public internet address —
23
+ loopback, link-local, the private ranges, the carrier-grade NAT range, and
24
+ the cloud metadata service that hands out instance credentials. The check is
25
+ on the RESOLVED address rather than the hostname, so a name that resolves to
26
+ `127.0.0.1` is refused, and it runs again at every redirect hop.
27
+ - It answers with one generic message for anything it refused, so the endpoint
28
+ cannot be used to find out what a hostname resolves to from inside your
29
+ network. The reason is logged on the server.
30
+ - `HEAD` first, `GET` only where a site answers 405 or 501 to it, and no
31
+ connection reuse between targets.
32
+
33
+ - [#746](https://github.com/valbuild/val/pull/746) [`e2bfc0e`](https://github.com/valbuild/val/commit/e2bfc0e40383fe25d3ec0473d1032f6264a8939f) Thanks [@freekh](https://github.com/freekh)! - A site hosted on Val (a managed project, with no repository of its own) can now be updated from the Studio. **Settings → Updates** says whether a newer version of the software the site runs on is available, lists the packages that move and their versions, and offers **Update site**.
34
+
35
+ Updating rebuilds the site in the browser on the new versions and publishes it through the ordinary publish, so it is checked before it goes live: if the updated site does not render, nothing changes and the site keeps running the old versions. Unpublished changes are kept and are **not** published by an update. After it goes live, reload the Studio to use the new one.
36
+
37
+ In Safari, which cannot build the site in the Studio's own page, Update site opens a tab that builds and publishes it, the same way a publish does there, and the Studio follows its progress.
38
+
39
+ A Studio that was opened before the site was updated no longer publishes: pressing Publish asks you to reload first, and nothing is saved until you do. Your unpublished changes are kept. Without this, a Studio left open from before an update would have built the site with the previous version of itself.
40
+
41
+ The versions come from the template the project was made from, as the platform last built it. A project whose code lives in a repository is not offered this; its dependencies are updated there.
42
+
43
+ For hosts: `@valbuild/server` forwards `GET` and `POST /api/val/publish-api/update-target` to the content service, beside `/build-target` and `/project-source`.
44
+
45
+ ### Patch Changes
46
+
47
+ - [#722](https://github.com/valbuild/val/pull/722) [`9b09bf3`](https://github.com/valbuild/val/commit/9b09bf38c9d5912f41fec1c18aa87455fd32f616) Thanks [@freekh](https://github.com/freekh)! - Show history for projects whose git branch is resolved by the server
48
+
49
+ A proxy-mode project that mirrors into a repository is committing to some
50
+ branch, and every commit and history listing is filed under it. But the Studio
51
+ reads `gitBranch` from `val.config` alone, where it is optional — so a project
52
+ that named its branch the usual deployment way (in the environment, e.g. from
53
+ `VERCEL_GIT_COMMIT_REF`) got a History pane reading "this project has no
54
+ `gitBranch` configured" and a status bar with no branch on it, while the server
55
+ behind it was busy committing to one.
56
+
57
+ `/stat` now fills in the branch the server resolved when `val.config` does not
58
+ name one. A branch in `val.config` still wins.
59
+
60
+ Nothing changes where there is no branch to name, and that is a real case
61
+ rather than a gap: git is optional in proxy mode — a project can run on
62
+ credentials alone, with no repository to mirror into — and `fs` mode has no
63
+ commits of its own. Those projects are handed no branch, and the Studio hides
64
+ what needs one rather than offering a History page that can only apologise.
65
+
66
+ - [#748](https://github.com/valbuild/val/pull/748) [`beda04b`](https://github.com/valbuild/val/commit/beda04bd326cbab18ed103e8d43917b16f43bd8c) Thanks [@freekh](https://github.com/freekh)! - A save is no longer refused once because an older answer from the server arrived after a newer one. The content service now reports a version of its list of changes, which goes up with every save, discard and publish. The Studio ignores any answer older than one it already has, including the answer to its own last save, discard or publish, so a discarded change can no longer briefly come back, and a published one can no longer briefly show as unpublished.
67
+ - Updated dependencies [[`8f60073`](https://github.com/valbuild/val/commit/8f60073e5490971a615cebbe8ea1243c67e43530), [`af7a4ba`](https://github.com/valbuild/val/commit/af7a4baa63da5d8a226166377a354cf2fc0c1d77), [`48ac9f0`](https://github.com/valbuild/val/commit/48ac9f06dd59a5b4ca60232b1ef198cf42f23aa6), [`daecf41`](https://github.com/valbuild/val/commit/daecf416f51990569a47a6a9ee9174b1a57f98c2), [`43b58f2`](https://github.com/valbuild/val/commit/43b58f2962840883badf91950da2c51b89d1c7cb), [`e2bfc0e`](https://github.com/valbuild/val/commit/e2bfc0e40383fe25d3ec0473d1032f6264a8939f), [`9b09bf3`](https://github.com/valbuild/val/commit/9b09bf38c9d5912f41fec1c18aa87455fd32f616), [`8e49bf4`](https://github.com/valbuild/val/commit/8e49bf41ad6a8ad3b01e502fb7ce0369baa316db), [`370d0df`](https://github.com/valbuild/val/commit/370d0df7ea45aeeafb4520318018d7c4e1c040d6), [`14877a8`](https://github.com/valbuild/val/commit/14877a85c5add4daa16836470b8739180a9fe8c6), [`beda04b`](https://github.com/valbuild/val/commit/beda04bd326cbab18ed103e8d43917b16f43bd8c)]:
68
+ - @valbuild/ui@0.137.0
69
+ - @valbuild/shared@0.137.0
70
+ - @valbuild/core@0.137.0
71
+
72
+ ## 0.136.10
73
+
74
+ ### Patch Changes
75
+
76
+ - [#743](https://github.com/valbuild/val/pull/743) [`fef29b0`](https://github.com/valbuild/val/commit/fef29b0d9e826e4e7e63a3ae61553137a3f9d280) Thanks [@freekh](https://github.com/freekh)! - Saving no longer gets stuck on "Changes cannot be saved: something else keeps changing them first" when another editor has an unpublished change and later work has been published.
77
+
78
+ A new change is now written on top of the latest change the content service has registered, which it reports alongside the list of pending changes, instead of the last change this deployment was shown. Since changes can be published independently, those two can differ for good: an unpublished change can sit before published ones that the running deployment already contains. The Studio and the MCP tools both name the reported head, and fall back to the old behaviour against a content service that does not report one.
79
+
80
+ - Updated dependencies [[`fef29b0`](https://github.com/valbuild/val/commit/fef29b0d9e826e4e7e63a3ae61553137a3f9d280)]:
81
+ - @valbuild/ui@0.136.10
82
+ - @valbuild/shared@0.136.10
83
+
3
84
  ## 0.136.9
4
85
 
5
86
  ### Patch Changes
@@ -141,6 +141,13 @@ export declare abstract class ValOps {
141
141
  commitSha?: CommitSha;
142
142
  sourcesSha: SourcesSha;
143
143
  patches: PatchId[];
144
+ /**
145
+ * The head of the chain, when the store reports one. See
146
+ * {@link OrderedPatches.headPatchId}.
147
+ */
148
+ headPatchId?: PatchId | null;
149
+ /** The chain version of that head. See {@link OrderedPatches.headVersion}. */
150
+ headVersion?: number;
144
151
  } | {
145
152
  type: "error";
146
153
  error: GenericErrorMessage;
@@ -396,6 +403,8 @@ export declare abstract class ValOps {
396
403
  createdAt: string;
397
404
  /** See {@link SaveSourceFilePatchResult} — absent where there are no groups. */
398
405
  patchGroupId?: string;
406
+ /** See {@link SaveSourceFilePatchResult}. */
407
+ headVersion?: number;
399
408
  }, {
400
409
  errorType: "other";
401
410
  error: GenericErrorMessage;
@@ -583,9 +592,12 @@ export declare abstract class ValOps {
583
592
  deleted: PatchId[];
584
593
  errors?: undefined;
585
594
  error?: undefined;
595
+ /** The chain version the delete moved the branch to, where reported. */
596
+ headVersion?: number;
586
597
  } | {
587
598
  deleted: PatchId[];
588
599
  errors: Record<PatchId, GenericErrorMessage>;
600
+ headVersion?: number;
589
601
  } | {
590
602
  error: GenericErrorMessage;
591
603
  errors?: undefined;
@@ -680,6 +692,12 @@ export type SaveSourceFilePatchResult = result.Result<{
680
692
  * client uses it to learn the id of the group its own first write created.
681
693
  */
682
694
  patchGroupId?: string;
695
+ /**
696
+ * The chain version this write made — see
697
+ * {@link OrderedPatches.headVersion}. Absent in `fs` mode and against a
698
+ * content service that predates it.
699
+ */
700
+ headVersion?: number;
683
701
  }, ({
684
702
  errorType: "other";
685
703
  } & GenericErrorMessage) | {
@@ -851,6 +869,28 @@ export type OrderedPatches = {
851
869
  } | null;
852
870
  }[];
853
871
  commits?: ValCommit[];
872
+ /**
873
+ * The head of the patch chain: the last patch registered on the branch,
874
+ * published or not. `null` when there is none.
875
+ *
876
+ * What a new patch names as its parent, and NOT the last of `patches` — see
877
+ * `chainHeadOf` in `@valbuild/shared` for why. Absent means the store does
878
+ * not report one: `ValOpsFS` (whose ordering log defines order, and which
879
+ * ignores the parent) and a content service that predates the field.
880
+ */
881
+ headPatchId?: PatchId | null;
882
+ /**
883
+ * The version of the chain {@link headPatchId} was read at.
884
+ *
885
+ * The content service bumps it with every write and every delete, in the
886
+ * transaction that makes the change, and reads it in the same statement as
887
+ * the head. `/stat` has more than one caller, so two answers can be in
888
+ * flight at once and land in either order; a client keeps the head with the
889
+ * highest version, and an answer that arrives after a newer one no longer
890
+ * puts its parent back. Absent wherever `headPatchId` is, and for the same
891
+ * reasons.
892
+ */
893
+ headVersion?: number;
854
894
  error?: GenericErrorMessage;
855
895
  errors?: PatchReadError[];
856
896
  unauthorized?: boolean;
@@ -862,6 +902,10 @@ export type OrderedPatchesMetadata = {
862
902
  })[];
863
903
  commits?: ValCommit[];
864
904
  deployments?: ValDeployment[];
905
+ /** See {@link OrderedPatches.headPatchId}. */
906
+ headPatchId?: OrderedPatches["headPatchId"];
907
+ /** See {@link OrderedPatches.headVersion}. */
908
+ headVersion?: OrderedPatches["headVersion"];
865
909
  error?: GenericErrorMessage;
866
910
  errors?: OrderedPatches["errors"];
867
911
  unauthorized?: boolean;
@@ -138,9 +138,11 @@ export declare class ValOpsFS extends ValOps {
138
138
  deleted: PatchId[];
139
139
  errors?: undefined;
140
140
  error?: undefined;
141
+ headVersion?: undefined;
141
142
  } | {
142
143
  deleted: PatchId[];
143
144
  errors: Record<PatchId, GenericErrorMessage>;
145
+ headVersion?: undefined;
144
146
  } | {
145
147
  error: GenericErrorMessage;
146
148
  errors?: undefined;
@@ -11,6 +11,15 @@ declare const CommitSha: z.ZodString & z.ZodType<CommitSha, string, z.core.$ZodT
11
11
  declare const BaseSha: z.ZodString & z.ZodType<BaseSha, string, z.core.$ZodTypeInternals<BaseSha, string>>;
12
12
  declare const AuthorId: z.ZodString & z.ZodType<AuthorId, string, z.core.$ZodTypeInternals<AuthorId, string>>;
13
13
  declare const ModuleFilePath: z.ZodString & z.ZodType<ModuleFilePath, string, z.core.$ZodTypeInternals<ModuleFilePath, string>>;
14
+ /**
15
+ * This client's own branch's entry in a per-branch version map.
16
+ *
17
+ * A delete can span branches, so the content service answers per branch. With
18
+ * no branch of its own (a build with no repository, where the service resolves
19
+ * it), the only entry is ours when there is exactly one; with several, none can
20
+ * be picked, and a wrong one would floor this client at another chain's count.
21
+ */
22
+ export declare function ownBranchVersion(headVersions: Record<string, number> | undefined, branch: string | undefined): number | undefined;
14
23
  export type PatchGroupMutationResult = {
15
24
  patchIds: PatchId[];
16
25
  status?: undefined;
@@ -197,7 +206,9 @@ export declare class ValOpsHttp extends ValOps {
197
206
  * An allow list rather than a prefix check, because this method holds a
198
207
  * credential and the browser chooses the path. `/publish/{id}` and its three
199
208
  * steps are the publish conversation; `/build-target` is what a build needs
200
- * to know before it starts; `/project-source` is what it builds.
209
+ * to know before it starts; `/project-source` is what it builds;
210
+ * `/update-target` is the same question as `/build-target` for a managed
211
+ * project moving onto its template's current dependencies.
201
212
  *
202
213
  * `/project-source` is here rather than on a route of its own because it is
203
214
  * one of the three things a publish asks for and none of them are useful
@@ -256,6 +267,10 @@ export declare class ValOpsHttp extends ValOps {
256
267
  patches: PatchId[];
257
268
  /** Of `patches`, the ones that have shipped. See the implementation. */
258
269
  appliedPatches: PatchId[];
270
+ /** The head of the chain. See {@link OrderedPatchesMetadata.headPatchId}. */
271
+ headPatchId?: PatchId | null;
272
+ /** The chain version of that head. See {@link OrderedPatchesMetadata.headVersion}. */
273
+ headVersion?: number;
259
274
  /** The newest commit, which is the publish head. */
260
275
  headCommitSha?: string;
261
276
  } | {
@@ -425,9 +440,11 @@ export declare class ValOpsHttp extends ValOps {
425
440
  deleted: PatchId[];
426
441
  errors?: undefined;
427
442
  error?: undefined;
443
+ headVersion?: number;
428
444
  } | {
429
445
  deleted: PatchId[];
430
446
  errors: Record<PatchId, GenericErrorMessage>;
447
+ headVersion?: number;
431
448
  } | {
432
449
  error: GenericErrorMessage;
433
450
  errors?: undefined;
@@ -457,6 +474,8 @@ export declare class ValOpsHttp extends ValOps {
457
474
  /** See `CommitResult.tree`: absent means not reported. */
458
475
  tree?: string;
459
476
  branch: string;
477
+ /** The chain version the publish moved the branch to, where reported. */
478
+ headVersion?: number;
460
479
  error?: undefined;
461
480
  } | {
462
481
  isNotFastForward?: boolean;
@@ -108,6 +108,12 @@ export type CommitResult = {
108
108
  */
109
109
  tree?: string;
110
110
  branch: string;
111
+ /**
112
+ * The chain version the publish moved the branch to, where the content
113
+ * service versions its chain and the publish applied anything. Passed
114
+ * on to the Studio, so a `/stat` read before the publish is dropped.
115
+ */
116
+ headVersion?: number;
111
117
  error?: undefined;
112
118
  } | {
113
119
  isNotFastForward?: boolean;