@valbuild/shared 0.138.4 → 0.139.1

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,56 @@
1
1
  # @valbuild/shared
2
2
 
3
+ ## 0.139.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#781](https://github.com/valbuild/val/pull/781) [`5ea70ce`](https://github.com/valbuild/val/commit/5ea70cefde3c74961cfa76b4a5f4c333b850b60a) Thanks [@freekh](https://github.com/freekh)! - Every open Studio now shows the same changes, staged the same way, as a reload would.
8
+
9
+ - Staging or unstaging a change in one browser or tab now shows up in your other open Studios right away, without a reload, and publishing from any of them ships the same set.
10
+ - A change you stage before you have made any edit of your own is saved straight away, instead of being kept in the tab until your first edit and lost if you reloaded first.
11
+ - If staging a change fails, the Studio now goes back to showing what is actually saved, instead of keeping the failed change on screen until a reload.
12
+
13
+ This needs the Val Build content service released alongside this version.
14
+
15
+ - Updated dependencies [[`db13bed`](https://github.com/valbuild/val/commit/db13bed902f9f9147feb5be07ce47fe8b5b143f9)]:
16
+ - @valbuild/core@0.139.1
17
+
18
+ ## 0.139.0
19
+
20
+ ### Minor Changes
21
+
22
+ - [#776](https://github.com/valbuild/val/pull/776) [`3eb5031`](https://github.com/valbuild/val/commit/3eb503167ae466ee586303c95efcc14665129481) Thanks [@freekh](https://github.com/freekh)! - **Breaking:** `.render({ as: "inline" })` now goes on the list, not on its items.
23
+
24
+ You now write `s.array(item).render({ as: "inline" })` and `s.record(item).render({ as: "inline" })`. Each item is then edited in its own row instead of in a preview row you click into. The list decides. The item schema stays reusable, and a page builder made of tagged blocks needs nothing on each block:
25
+
26
+ ```ts
27
+ // before
28
+ s.array(
29
+ s.discriminatedUnion(
30
+ "type",
31
+ hero.render({ as: "inline" }),
32
+ text.render({ as: "inline" }),
33
+ ),
34
+ );
35
+
36
+ // after
37
+ s.array(s.discriminatedUnion("type", hero, text)).render({ as: "inline" });
38
+ ```
39
+
40
+ What changed:
41
+
42
+ - Only `s.array()`, `s.record()` and `s.keyOf()` have `.render(...)` now. On every other schema the method is gone, so the old placement shows up as a type error. Move the render out one level.
43
+ - The render only affects the list's own items. A list nested inside one of those items keeps its default unless it has its own `.render`.
44
+ - `s.router()`, `s.imageset()` and `s.fileset()` throw if you give them a render, because pages and media have their own editors.
45
+ - `s.keyOf(...).render({ as: "inline" })` means the same as before: the selected entry's content is shown below the dropdown.
46
+
47
+ **Watch for one case that still compiles:** an array or record that is itself the item of another list. `s.record(s.array(s.string()).render({ as: "inline" }))` used to show the record's arrays inline. Now it shows each array's strings inline. To keep the old layout, write `s.record(s.array(s.string())).render({ as: "inline" })`.
48
+
49
+ ### Patch Changes
50
+
51
+ - Updated dependencies [[`3eb5031`](https://github.com/valbuild/val/commit/3eb503167ae466ee586303c95efcc14665129481)]:
52
+ - @valbuild/core@0.139.0
53
+
3
54
  ## 0.138.4
4
55
 
5
56
  ### Patch Changes
@@ -442,6 +442,13 @@ export declare const Api: {
442
442
  headCommitSha: z.ZodOptional<z.ZodString>;
443
443
  headPatchId: z.ZodOptional<z.ZodNullable<z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>>>;
444
444
  headVersion: z.ZodOptional<z.ZodNumber>;
445
+ patchGroups: z.ZodOptional<z.ZodArray<z.ZodObject<{
446
+ patchGroupId: z.ZodString;
447
+ authorId: z.ZodNullable<z.ZodString>;
448
+ createdAt: z.ZodString;
449
+ publishedAt: z.ZodNullable<z.ZodString>;
450
+ patchIds: z.ZodArray<z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>>;
451
+ }, z.core.$strip>>>;
445
452
  commits: z.ZodArray<z.ZodObject<{
446
453
  commitSha: z.ZodString;
447
454
  clientCommitSha: z.ZodNullable<z.ZodString>;
@@ -863,7 +870,7 @@ export declare const Api: {
863
870
  PUT: {
864
871
  req: {
865
872
  body: z.ZodObject<{
866
- patchGroupId: z.ZodString;
873
+ patchGroupId: z.ZodOptional<z.ZodString>;
867
874
  patchIds: z.ZodArray<z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>>;
868
875
  withPatchIds: z.ZodOptional<z.ZodArray<z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>>>;
869
876
  }, z.core.$strip>;
@@ -894,15 +901,16 @@ export declare const Api: {
894
901
  }, z.core.$strip>, z.ZodObject<{
895
902
  status: z.ZodLiteral<200>;
896
903
  json: z.ZodObject<{
897
- patchGroupId: z.ZodString;
904
+ patchGroupId: z.ZodNullable<z.ZodString>;
898
905
  patchIds: z.ZodArray<z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>>;
906
+ headVersion: z.ZodOptional<z.ZodNumber>;
899
907
  }, z.core.$strip>;
900
908
  }, z.core.$strip>]>;
901
909
  };
902
910
  DELETE: {
903
911
  req: {
904
912
  body: z.ZodObject<{
905
- patchGroupId: z.ZodString;
913
+ patchGroupId: z.ZodOptional<z.ZodString>;
906
914
  patchIds: z.ZodArray<z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>>;
907
915
  withPatchIds: z.ZodOptional<z.ZodArray<z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>>>;
908
916
  }, z.core.$strip>;
@@ -933,8 +941,9 @@ export declare const Api: {
933
941
  }, z.core.$strip>, z.ZodObject<{
934
942
  status: z.ZodLiteral<200>;
935
943
  json: z.ZodObject<{
936
- patchGroupId: z.ZodString;
944
+ patchGroupId: z.ZodNullable<z.ZodString>;
937
945
  patchIds: z.ZodArray<z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>>;
946
+ headVersion: z.ZodOptional<z.ZodNumber>;
938
947
  }, z.core.$strip>;
939
948
  }, z.core.$strip>]>;
940
949
  };
@@ -86,9 +86,6 @@ export declare const SerializedSettingsSchema: z.ZodType<SerializedSettingsSchem
86
86
  */
87
87
  export declare const SerializedValViewSchema: z.ZodObject<{
88
88
  type: z.ZodLiteral<"view">;
89
- render: z.ZodOptional<z.ZodOptional<z.ZodObject<{
90
- as: z.ZodLiteral<"inline">;
91
- }, z.core.$strip>>>;
92
89
  moduleFilePath: z.ZodType<import("@valbuild/core").ModuleFilePath, unknown, z.core.$ZodTypeInternals<import("@valbuild/core").ModuleFilePath, unknown>>;
93
90
  opt: z.ZodLiteral<false>;
94
91
  readonly: z.ZodOptional<z.ZodBoolean>;
@@ -987,7 +987,8 @@ var _excluded = ["directory"];
987
987
 
988
988
  // A render is static config, so unlike a `preview` it travels WHOLE — this
989
989
  // is the field the editor reads the layout from. See `core/src/render.ts`.
990
- // Every field can carry `{ as: "inline" }`, and that is all a render says.
990
+ // Only array, record and keyOf carry one, and `{ as: "inline" }` is all it
991
+ // says. A stale `render` on any other schema is stripped here, harmlessly.
991
992
  // NB: these z.objects STRIP unknown keys, so a render variant that is not
992
993
  // declared here is silently dropped in transit — add it here when it is added
993
994
  // to `render.ts`.
@@ -1009,7 +1010,6 @@ var FieldRender = InlineRender.optional();
1009
1010
  * - those differ per schema, so there is nothing to share.
1010
1011
  */
1011
1012
  var commonSchemaFields = {
1012
- render: FieldRender,
1013
1013
  preview: zod.z.literal(true).optional(),
1014
1014
  // Whether the schema declares a `.validate()`. The function cannot serialize,
1015
1015
  // so this flag is what tells the Studio to run the custom validators on the
@@ -1068,6 +1068,7 @@ var SerializedObjectSchema = zod.z.lazy(function () {
1068
1068
  });
1069
1069
  var SerializedArraySchema = zod.z.lazy(function () {
1070
1070
  return zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
1071
+ render: FieldRender,
1071
1072
  type: zod.z.literal("array"),
1072
1073
  item: SerializedSchema,
1073
1074
  opt: zod.z["boolean"]()
@@ -1160,6 +1161,7 @@ var SerializedRichTextSchema = zod.z.object(getSitemapTree._objectSpread2(getSit
1160
1161
  }));
1161
1162
  var SerializedRecordSchema = zod.z.lazy(function () {
1162
1163
  return zod.z.preprocess(readLegacyDirectoryAsDir, zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
1164
+ render: FieldRender,
1163
1165
  type: zod.z.literal("record"),
1164
1166
  item: SerializedSchema,
1165
1167
  opt: zod.z["boolean"](),
@@ -1176,6 +1178,7 @@ var SerializedRecordSchema = zod.z.lazy(function () {
1176
1178
  });
1177
1179
  var SerializedKeyOfSchema = zod.z.lazy(function () {
1178
1180
  return zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
1181
+ render: FieldRender,
1179
1182
  type: zod.z.literal("keyOf"),
1180
1183
  path: SourcePath,
1181
1184
  schema: zod.z.union([zod.z.object({
@@ -1235,7 +1238,6 @@ var SerializedCodeSchema = zod.z.object(getSitemapTree._objectSpread2(getSitemap
1235
1238
  }));
1236
1239
  var SerializedLocaleSchema = zod.z.object({
1237
1240
  type: zod.z.literal("locale"),
1238
- render: FieldRender,
1239
1241
  preview: zod.z.literal(true).optional(),
1240
1242
  opt: zod.z["boolean"](),
1241
1243
  customValidate: zod.z["boolean"]().optional(),
@@ -1261,7 +1263,7 @@ var SerializedRouteSchema = zod.z.object(getSitemapTree._objectSpread2(getSitema
1261
1263
 
1262
1264
  // A settings module, and each section inside one, serialize as this - the
1263
1265
  // shape is recursive because `items` holds sections which are themselves
1264
- // settings schemas. `s.settings()` never writes render/preview/customValidate
1266
+ // settings schemas. `s.settings()` never writes preview/customValidate
1265
1267
  // (see core/src/schema/settings.ts), but they are accepted here because they
1266
1268
  // are part of the declared type.
1267
1269
  var SerializedSettingsSchema = zod.z.lazy(function () {
@@ -1287,7 +1289,6 @@ var SerializedSettingsSchema = zod.z.lazy(function () {
1287
1289
  */
1288
1290
  var SerializedValViewSchema = zod.z.object({
1289
1291
  type: zod.z.literal("view"),
1290
- render: FieldRender.optional(),
1291
1292
  moduleFilePath: ModuleFilePath$1,
1292
1293
  opt: zod.z.literal(false),
1293
1294
  readonly: zod.z["boolean"]().optional(),
@@ -2027,6 +2028,14 @@ var Api = {
2027
2028
  * highest version. Optional, for the same reason `headPatchId` is.
2028
2029
  */
2029
2030
  headVersion: zod.z.number().optional(),
2031
+ /**
2032
+ * Every group on the branch and which listed patches it holds,
2033
+ * read with the list and `headVersion`. What a Studio's view of
2034
+ * the groups is taken from, so a stage or an unstage made in
2035
+ * another browser reaches it with the next stat. Absent where
2036
+ * the content service has no groups.
2037
+ */
2038
+ patchGroups: zod.z.array(PatchGroup).optional(),
2030
2039
  commits: zod.z.array(ValCommit),
2031
2040
  /**
2032
2041
  * The publishes the content service knows about.
@@ -2426,7 +2435,12 @@ var Api = {
2426
2435
  PUT: {
2427
2436
  req: {
2428
2437
  body: zod.z.object({
2429
- patchGroupId: zod.z.string(),
2438
+ /**
2439
+ * The group to stage into. Absent means the caller's open group on
2440
+ * the branch, created if there is none — which is what the Studio
2441
+ * sends, so a stage never has to wait for a group to exist.
2442
+ */
2443
+ patchGroupId: zod.z.string().optional(),
2430
2444
  /** What the user asked to stage. */
2431
2445
  patchIds: zod.z.array(PatchId),
2432
2446
  /*
@@ -2464,15 +2478,23 @@ var Api = {
2464
2478
  }), zod.z.object({
2465
2479
  status: zod.z.literal(200),
2466
2480
  json: zod.z.object({
2467
- patchGroupId: zod.z.string(),
2468
- patchIds: zod.z.array(PatchId)
2481
+ /** `null` for an unstage when the caller has no open group. */
2482
+ patchGroupId: zod.z.string().nullable(),
2483
+ patchIds: zod.z.array(PatchId),
2484
+ /**
2485
+ * The chain version the change committed at. The client keeps its
2486
+ * own view of the change until a stat at least this new shows it.
2487
+ * Absent from a content service that predates it.
2488
+ */
2489
+ headVersion: zod.z.number().optional()
2469
2490
  })
2470
2491
  })])
2471
2492
  },
2472
2493
  DELETE: {
2473
2494
  req: {
2474
2495
  body: zod.z.object({
2475
- patchGroupId: zod.z.string(),
2496
+ /** See the PUT. Absent with no open group is a no-op. */
2497
+ patchGroupId: zod.z.string().optional(),
2476
2498
  /** What the user asked to unstage. */
2477
2499
  patchIds: zod.z.array(PatchId),
2478
2500
  /** What has to go with it: everything built on top of it. */
@@ -2497,8 +2519,15 @@ var Api = {
2497
2519
  }), zod.z.object({
2498
2520
  status: zod.z.literal(200),
2499
2521
  json: zod.z.object({
2500
- patchGroupId: zod.z.string(),
2501
- patchIds: zod.z.array(PatchId)
2522
+ /** `null` for an unstage when the caller has no open group. */
2523
+ patchGroupId: zod.z.string().nullable(),
2524
+ patchIds: zod.z.array(PatchId),
2525
+ /**
2526
+ * The chain version the change committed at. The client keeps its
2527
+ * own view of the change until a stat at least this new shows it.
2528
+ * Absent from a content service that predates it.
2529
+ */
2530
+ headVersion: zod.z.number().optional()
2502
2531
  })
2503
2532
  })])
2504
2533
  }
@@ -987,7 +987,8 @@ var _excluded = ["directory"];
987
987
 
988
988
  // A render is static config, so unlike a `preview` it travels WHOLE — this
989
989
  // is the field the editor reads the layout from. See `core/src/render.ts`.
990
- // Every field can carry `{ as: "inline" }`, and that is all a render says.
990
+ // Only array, record and keyOf carry one, and `{ as: "inline" }` is all it
991
+ // says. A stale `render` on any other schema is stripped here, harmlessly.
991
992
  // NB: these z.objects STRIP unknown keys, so a render variant that is not
992
993
  // declared here is silently dropped in transit — add it here when it is added
993
994
  // to `render.ts`.
@@ -1009,7 +1010,6 @@ var FieldRender = InlineRender.optional();
1009
1010
  * - those differ per schema, so there is nothing to share.
1010
1011
  */
1011
1012
  var commonSchemaFields = {
1012
- render: FieldRender,
1013
1013
  preview: zod.z.literal(true).optional(),
1014
1014
  // Whether the schema declares a `.validate()`. The function cannot serialize,
1015
1015
  // so this flag is what tells the Studio to run the custom validators on the
@@ -1068,6 +1068,7 @@ var SerializedObjectSchema = zod.z.lazy(function () {
1068
1068
  });
1069
1069
  var SerializedArraySchema = zod.z.lazy(function () {
1070
1070
  return zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
1071
+ render: FieldRender,
1071
1072
  type: zod.z.literal("array"),
1072
1073
  item: SerializedSchema,
1073
1074
  opt: zod.z["boolean"]()
@@ -1160,6 +1161,7 @@ var SerializedRichTextSchema = zod.z.object(getSitemapTree._objectSpread2(getSit
1160
1161
  }));
1161
1162
  var SerializedRecordSchema = zod.z.lazy(function () {
1162
1163
  return zod.z.preprocess(readLegacyDirectoryAsDir, zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
1164
+ render: FieldRender,
1163
1165
  type: zod.z.literal("record"),
1164
1166
  item: SerializedSchema,
1165
1167
  opt: zod.z["boolean"](),
@@ -1176,6 +1178,7 @@ var SerializedRecordSchema = zod.z.lazy(function () {
1176
1178
  });
1177
1179
  var SerializedKeyOfSchema = zod.z.lazy(function () {
1178
1180
  return zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
1181
+ render: FieldRender,
1179
1182
  type: zod.z.literal("keyOf"),
1180
1183
  path: SourcePath,
1181
1184
  schema: zod.z.union([zod.z.object({
@@ -1235,7 +1238,6 @@ var SerializedCodeSchema = zod.z.object(getSitemapTree._objectSpread2(getSitemap
1235
1238
  }));
1236
1239
  var SerializedLocaleSchema = zod.z.object({
1237
1240
  type: zod.z.literal("locale"),
1238
- render: FieldRender,
1239
1241
  preview: zod.z.literal(true).optional(),
1240
1242
  opt: zod.z["boolean"](),
1241
1243
  customValidate: zod.z["boolean"]().optional(),
@@ -1261,7 +1263,7 @@ var SerializedRouteSchema = zod.z.object(getSitemapTree._objectSpread2(getSitema
1261
1263
 
1262
1264
  // A settings module, and each section inside one, serialize as this - the
1263
1265
  // shape is recursive because `items` holds sections which are themselves
1264
- // settings schemas. `s.settings()` never writes render/preview/customValidate
1266
+ // settings schemas. `s.settings()` never writes preview/customValidate
1265
1267
  // (see core/src/schema/settings.ts), but they are accepted here because they
1266
1268
  // are part of the declared type.
1267
1269
  var SerializedSettingsSchema = zod.z.lazy(function () {
@@ -1287,7 +1289,6 @@ var SerializedSettingsSchema = zod.z.lazy(function () {
1287
1289
  */
1288
1290
  var SerializedValViewSchema = zod.z.object({
1289
1291
  type: zod.z.literal("view"),
1290
- render: FieldRender.optional(),
1291
1292
  moduleFilePath: ModuleFilePath$1,
1292
1293
  opt: zod.z.literal(false),
1293
1294
  readonly: zod.z["boolean"]().optional(),
@@ -2027,6 +2028,14 @@ var Api = {
2027
2028
  * highest version. Optional, for the same reason `headPatchId` is.
2028
2029
  */
2029
2030
  headVersion: zod.z.number().optional(),
2031
+ /**
2032
+ * Every group on the branch and which listed patches it holds,
2033
+ * read with the list and `headVersion`. What a Studio's view of
2034
+ * the groups is taken from, so a stage or an unstage made in
2035
+ * another browser reaches it with the next stat. Absent where
2036
+ * the content service has no groups.
2037
+ */
2038
+ patchGroups: zod.z.array(PatchGroup).optional(),
2030
2039
  commits: zod.z.array(ValCommit),
2031
2040
  /**
2032
2041
  * The publishes the content service knows about.
@@ -2426,7 +2435,12 @@ var Api = {
2426
2435
  PUT: {
2427
2436
  req: {
2428
2437
  body: zod.z.object({
2429
- patchGroupId: zod.z.string(),
2438
+ /**
2439
+ * The group to stage into. Absent means the caller's open group on
2440
+ * the branch, created if there is none — which is what the Studio
2441
+ * sends, so a stage never has to wait for a group to exist.
2442
+ */
2443
+ patchGroupId: zod.z.string().optional(),
2430
2444
  /** What the user asked to stage. */
2431
2445
  patchIds: zod.z.array(PatchId),
2432
2446
  /*
@@ -2464,15 +2478,23 @@ var Api = {
2464
2478
  }), zod.z.object({
2465
2479
  status: zod.z.literal(200),
2466
2480
  json: zod.z.object({
2467
- patchGroupId: zod.z.string(),
2468
- patchIds: zod.z.array(PatchId)
2481
+ /** `null` for an unstage when the caller has no open group. */
2482
+ patchGroupId: zod.z.string().nullable(),
2483
+ patchIds: zod.z.array(PatchId),
2484
+ /**
2485
+ * The chain version the change committed at. The client keeps its
2486
+ * own view of the change until a stat at least this new shows it.
2487
+ * Absent from a content service that predates it.
2488
+ */
2489
+ headVersion: zod.z.number().optional()
2469
2490
  })
2470
2491
  })])
2471
2492
  },
2472
2493
  DELETE: {
2473
2494
  req: {
2474
2495
  body: zod.z.object({
2475
- patchGroupId: zod.z.string(),
2496
+ /** See the PUT. Absent with no open group is a no-op. */
2497
+ patchGroupId: zod.z.string().optional(),
2476
2498
  /** What the user asked to unstage. */
2477
2499
  patchIds: zod.z.array(PatchId),
2478
2500
  /** What has to go with it: everything built on top of it. */
@@ -2497,8 +2519,15 @@ var Api = {
2497
2519
  }), zod.z.object({
2498
2520
  status: zod.z.literal(200),
2499
2521
  json: zod.z.object({
2500
- patchGroupId: zod.z.string(),
2501
- patchIds: zod.z.array(PatchId)
2522
+ /** `null` for an unstage when the caller has no open group. */
2523
+ patchGroupId: zod.z.string().nullable(),
2524
+ patchIds: zod.z.array(PatchId),
2525
+ /**
2526
+ * The chain version the change committed at. The client keeps its
2527
+ * own view of the change until a stat at least this new shows it.
2528
+ * Absent from a content service that predates it.
2529
+ */
2530
+ headVersion: zod.z.number().optional()
2502
2531
  })
2503
2532
  })])
2504
2533
  }
@@ -980,7 +980,8 @@ var _excluded = ["directory"];
980
980
 
981
981
  // A render is static config, so unlike a `preview` it travels WHOLE — this
982
982
  // is the field the editor reads the layout from. See `core/src/render.ts`.
983
- // Every field can carry `{ as: "inline" }`, and that is all a render says.
983
+ // Only array, record and keyOf carry one, and `{ as: "inline" }` is all it
984
+ // says. A stale `render` on any other schema is stripped here, harmlessly.
984
985
  // NB: these z.objects STRIP unknown keys, so a render variant that is not
985
986
  // declared here is silently dropped in transit — add it here when it is added
986
987
  // to `render.ts`.
@@ -1002,7 +1003,6 @@ var FieldRender = InlineRender.optional();
1002
1003
  * - those differ per schema, so there is nothing to share.
1003
1004
  */
1004
1005
  var commonSchemaFields = {
1005
- render: FieldRender,
1006
1006
  preview: z.literal(true).optional(),
1007
1007
  // Whether the schema declares a `.validate()`. The function cannot serialize,
1008
1008
  // so this flag is what tells the Studio to run the custom validators on the
@@ -1061,6 +1061,7 @@ var SerializedObjectSchema = z.lazy(function () {
1061
1061
  });
1062
1062
  var SerializedArraySchema = z.lazy(function () {
1063
1063
  return z.object(_objectSpread2(_objectSpread2({}, commonSchemaFields), {}, {
1064
+ render: FieldRender,
1064
1065
  type: z.literal("array"),
1065
1066
  item: SerializedSchema,
1066
1067
  opt: z["boolean"]()
@@ -1153,6 +1154,7 @@ var SerializedRichTextSchema = z.object(_objectSpread2(_objectSpread2({}, common
1153
1154
  }));
1154
1155
  var SerializedRecordSchema = z.lazy(function () {
1155
1156
  return z.preprocess(readLegacyDirectoryAsDir, z.object(_objectSpread2(_objectSpread2({}, commonSchemaFields), {}, {
1157
+ render: FieldRender,
1156
1158
  type: z.literal("record"),
1157
1159
  item: SerializedSchema,
1158
1160
  opt: z["boolean"](),
@@ -1169,6 +1171,7 @@ var SerializedRecordSchema = z.lazy(function () {
1169
1171
  });
1170
1172
  var SerializedKeyOfSchema = z.lazy(function () {
1171
1173
  return z.object(_objectSpread2(_objectSpread2({}, commonSchemaFields), {}, {
1174
+ render: FieldRender,
1172
1175
  type: z.literal("keyOf"),
1173
1176
  path: SourcePath,
1174
1177
  schema: z.union([z.object({
@@ -1228,7 +1231,6 @@ var SerializedCodeSchema = z.object(_objectSpread2(_objectSpread2({}, commonSche
1228
1231
  }));
1229
1232
  var SerializedLocaleSchema = z.object({
1230
1233
  type: z.literal("locale"),
1231
- render: FieldRender,
1232
1234
  preview: z.literal(true).optional(),
1233
1235
  opt: z["boolean"](),
1234
1236
  customValidate: z["boolean"]().optional(),
@@ -1254,7 +1256,7 @@ var SerializedRouteSchema = z.object(_objectSpread2(_objectSpread2({}, commonSch
1254
1256
 
1255
1257
  // A settings module, and each section inside one, serialize as this - the
1256
1258
  // shape is recursive because `items` holds sections which are themselves
1257
- // settings schemas. `s.settings()` never writes render/preview/customValidate
1259
+ // settings schemas. `s.settings()` never writes preview/customValidate
1258
1260
  // (see core/src/schema/settings.ts), but they are accepted here because they
1259
1261
  // are part of the declared type.
1260
1262
  var SerializedSettingsSchema = z.lazy(function () {
@@ -1280,7 +1282,6 @@ var SerializedSettingsSchema = z.lazy(function () {
1280
1282
  */
1281
1283
  var SerializedValViewSchema = z.object({
1282
1284
  type: z.literal("view"),
1283
- render: FieldRender.optional(),
1284
1285
  moduleFilePath: ModuleFilePath$1,
1285
1286
  opt: z.literal(false),
1286
1287
  readonly: z["boolean"]().optional(),
@@ -2020,6 +2021,14 @@ var Api = {
2020
2021
  * highest version. Optional, for the same reason `headPatchId` is.
2021
2022
  */
2022
2023
  headVersion: z.number().optional(),
2024
+ /**
2025
+ * Every group on the branch and which listed patches it holds,
2026
+ * read with the list and `headVersion`. What a Studio's view of
2027
+ * the groups is taken from, so a stage or an unstage made in
2028
+ * another browser reaches it with the next stat. Absent where
2029
+ * the content service has no groups.
2030
+ */
2031
+ patchGroups: z.array(PatchGroup).optional(),
2023
2032
  commits: z.array(ValCommit),
2024
2033
  /**
2025
2034
  * The publishes the content service knows about.
@@ -2419,7 +2428,12 @@ var Api = {
2419
2428
  PUT: {
2420
2429
  req: {
2421
2430
  body: z.object({
2422
- patchGroupId: z.string(),
2431
+ /**
2432
+ * The group to stage into. Absent means the caller's open group on
2433
+ * the branch, created if there is none — which is what the Studio
2434
+ * sends, so a stage never has to wait for a group to exist.
2435
+ */
2436
+ patchGroupId: z.string().optional(),
2423
2437
  /** What the user asked to stage. */
2424
2438
  patchIds: z.array(PatchId),
2425
2439
  /*
@@ -2457,15 +2471,23 @@ var Api = {
2457
2471
  }), z.object({
2458
2472
  status: z.literal(200),
2459
2473
  json: z.object({
2460
- patchGroupId: z.string(),
2461
- patchIds: z.array(PatchId)
2474
+ /** `null` for an unstage when the caller has no open group. */
2475
+ patchGroupId: z.string().nullable(),
2476
+ patchIds: z.array(PatchId),
2477
+ /**
2478
+ * The chain version the change committed at. The client keeps its
2479
+ * own view of the change until a stat at least this new shows it.
2480
+ * Absent from a content service that predates it.
2481
+ */
2482
+ headVersion: z.number().optional()
2462
2483
  })
2463
2484
  })])
2464
2485
  },
2465
2486
  DELETE: {
2466
2487
  req: {
2467
2488
  body: z.object({
2468
- patchGroupId: z.string(),
2489
+ /** See the PUT. Absent with no open group is a no-op. */
2490
+ patchGroupId: z.string().optional(),
2469
2491
  /** What the user asked to unstage. */
2470
2492
  patchIds: z.array(PatchId),
2471
2493
  /** What has to go with it: everything built on top of it. */
@@ -2490,8 +2512,15 @@ var Api = {
2490
2512
  }), z.object({
2491
2513
  status: z.literal(200),
2492
2514
  json: z.object({
2493
- patchGroupId: z.string(),
2494
- patchIds: z.array(PatchId)
2515
+ /** `null` for an unstage when the caller has no open group. */
2516
+ patchGroupId: z.string().nullable(),
2517
+ patchIds: z.array(PatchId),
2518
+ /**
2519
+ * The chain version the change committed at. The client keeps its
2520
+ * own view of the change until a stat at least this new shows it.
2521
+ * Absent from a content service that predates it.
2522
+ */
2523
+ headVersion: z.number().optional()
2495
2524
  })
2496
2525
  })])
2497
2526
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valbuild/shared",
3
- "version": "0.138.4",
3
+ "version": "0.139.1",
4
4
  "private": false,
5
5
  "description": "Val shared types and utilities",
6
6
  "repository": {
@@ -37,7 +37,7 @@
37
37
  "flexsearch": "^0.8.212",
38
38
  "zod": "^4.4.3",
39
39
  "zod-validation-error": "^5.0.0",
40
- "@valbuild/core": "0.138.2"
40
+ "@valbuild/core": "0.139.1"
41
41
  },
42
42
  "files": [
43
43
  "CHANGELOG.md",