@valbuild/shared 0.130.0 → 0.134.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,116 @@
1
1
  # @valbuild/shared
2
2
 
3
+ ## 0.134.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#680](https://github.com/valbuild/val/pull/680) [`eaa265e`](https://github.com/valbuild/val/commit/eaa265e78d9f6d2a1b685c38901612b8a3704eed) Thanks [@freekh](https://github.com/freekh)! - Add `s.view()`: point at another module, so editors can reach it from the page it belongs to.
8
+
9
+ Content that has to live in its own module — a `keyOf` target, shared settings, a route-keyed record — is invisible from the page an editor thinks of it as part of. A view field puts a row on that page's screen that leads to it:
10
+
11
+ ```ts
12
+ import employeesVal from "../data/employees.val";
13
+
14
+ const schema = s.object({
15
+ title: s.string(),
16
+ employees: s.view(employeesVal),
17
+ });
18
+
19
+ export default c.define("/app/menneskene/page.val.ts", schema, {
20
+ title: "Våre folk",
21
+ employees: { view: "/data/employees.val.ts" },
22
+ });
23
+ ```
24
+
25
+ The source is a pointer and nothing else. The module it names keeps its own source, patches, validation and address, and an editor who follows the row lands on that module's own screen — so it is clear they are changing something other pages use too.
26
+
27
+ A few things worth knowing:
28
+
29
+ - **The path autocompletes, and a wrong one does not compile.** A module now carries its own id in its type, so the source type of the field above is the literal `{ view: "/data/employees.val.ts" }`.
30
+ - **It is not readable in code.** `useVal(pageVal).employees` is a `ValView<…>` — an opaque pointer with no fields on it. Read the module it names directly, as before.
31
+ - **`view` is now a reserved object key**, like `_type` and `patch_id`: `s.object({ view: ... })` no longer compiles. A single `view: string` key is what a view pointer looks like, and an ordinary object with that shape would be indistinguishable from one.
32
+ - **Views may not form a cycle.** `A → B → A`, and a module viewing itself, are reported as module errors by `val validate` and in the Studio.
33
+ - **A pointer that disagrees with its schema is repaired automatically.** It can only happen in hand-written JSON, and the schema is the authority, so `val validate --fix` and saving in the Studio both write the module the schema names.
34
+ - **A view's `hidden` and `readonly` are its own, never the module's it points at.** A view whose target is hidden is still shown, and still leads there.
35
+
36
+ That last one comes with a change to what `hidden()` means on a **module's own schema**, which is the other half of making a shared module usable:
37
+
38
+ ```ts
39
+ // Not in the nav, and on exactly one page.
40
+ export default c.define("/data/employees.val.ts", s.record(...).hidden(), { ... });
41
+ ```
42
+
43
+ It now means the nav does not list the module — the Explorer for an ordinary module, Media for a gallery — and nothing more. Previously it also blanked the module's own page, so a module you had hidden was still in the nav and showed nothing when opened. A hidden module is now reached from an `s.view()` row, from search or from a validation error, and renders in full when you get there.
44
+
45
+ One gap worth naming rather than leaving to be discovered: a view pointing at a
46
+ module the project does not have is reported by the FIELD — the row says the
47
+ target is missing — but not by `val validate`. The schema check compares the
48
+ pointer against the schema, and the cycle check deliberately skips a target that
49
+ is not a module of the project, so neither catches it. A project-level check
50
+ belongs with them and is not here yet.
51
+
52
+ ### Patch Changes
53
+
54
+ - Updated dependencies [[`16c49ea`](https://github.com/valbuild/val/commit/16c49ea6dd97c7a96bbfdf211af9bab5884579e2), [`eaa265e`](https://github.com/valbuild/val/commit/eaa265e78d9f6d2a1b685c38901612b8a3704eed)]:
55
+ - @valbuild/core@0.134.0
56
+
57
+ ## 0.133.0
58
+
59
+ ### Minor Changes
60
+
61
+ - [#700](https://github.com/valbuild/val/pull/700) [`802412b`](https://github.com/valbuild/val/commit/802412b92c06bc1abbca78c86885e39c8710dd83) Thanks [@freekh](https://github.com/freekh)! - http mode no longer needs a git repository
62
+
63
+ A Val app can now run in http mode with no commit and no branch — its content
64
+ service is the store of record, and git is an optional mirror of the code. This
65
+ is what `fs` mode has always done: it has never had git, and it works.
66
+
67
+ Before this, `VAL_API_KEY` and `VAL_SECRET` were not enough. `VAL_GIT_COMMIT`
68
+ and `VAL_GIT_BRANCH` were required too, so a deployment with no commit to name
69
+ either threw at boot or fell through to `fs` mode and reached for a working
70
+ tree that was not there.
71
+
72
+ **Breaking, if you pass `http` options in code.** `gitCommit` and `gitBranch`
73
+ are replaced by one optional `git`:
74
+
75
+ ```diff
76
+ initValServer(valModules, config, {
77
+ http: {
78
+ apiKey,
79
+ valSecret,
80
+ - gitCommit: process.env.VAL_GIT_COMMIT,
81
+ - gitBranch: "main",
82
+ + // Only for a project whose content is mirrored into a repository.
83
+ + // Omit it entirely otherwise.
84
+ + git: { commit: process.env.VAL_GIT_COMMIT, branch: "main" },
85
+ },
86
+ })
87
+ ```
88
+
89
+ `VAL_GIT_COMMIT` and `VAL_GIT_BRANCH` still work and are still read; they are
90
+ simply no longer required. Set both or neither — a commit without a branch, or
91
+ a branch without a commit, is refused at startup with a message naming the
92
+ missing half, rather than failing later at a publish.
93
+
94
+ **What a commit is for, where you have one.** Turning pending patches into new
95
+ `.val.ts` text means reading the current text first, and that read goes to the
96
+ content service at that commit. It is the publish path, not the serving path: a
97
+ committed render reads the source compiled into the build and asks the content
98
+ service nothing. With no repository there is nothing to write `.val.ts` into,
99
+ so a publish records the module's data and its schema and skips the file — and
100
+ that data is what history reads, so nothing is lost.
101
+
102
+ **A publish can now be refused by name, before it is attempted.** If a project
103
+ mirrors its commits into a repository but the running deployment was built
104
+ before that repository existed, it has no commit to write the mirror against.
105
+ Publishing anyway would save the content and silently leave the repository
106
+ behind. The Studio now disables Publish and shows why, and `/save` refuses with
107
+ a `no-base` code instead of failing partway.
108
+
109
+ **Also:** `ValCommit` and `HistoricalCommit` have nullable `parentCommitSha`
110
+ and `clientCommitSha`, and `/stat`'s `commitSha` is optional. A root commit has
111
+ no parent, and a publisher with no repository does not report where it was. If
112
+ you read these fields, handle `null`.
113
+
3
114
  ## 0.130.0
4
115
 
5
116
  ### Patch Changes
@@ -423,6 +423,10 @@ export declare const Api: {
423
423
  profileId: z.ZodNullable<z.ZodString>;
424
424
  mode: z.ZodUnion<readonly [z.ZodLiteral<"http">, z.ZodLiteral<"fs">]>;
425
425
  jsonEntriesSha: z.ZodOptional<z.ZodString>;
426
+ publishRefusal: z.ZodOptional<z.ZodObject<{
427
+ code: z.ZodLiteral<"no-base">;
428
+ message: z.ZodString;
429
+ }, z.core.$strip>>;
426
430
  }, z.core.$strip>, z.ZodObject<{
427
431
  type: z.ZodLiteral<"use-websocket">;
428
432
  url: z.ZodString;
@@ -430,14 +434,14 @@ export declare const Api: {
430
434
  baseSha: z.ZodString;
431
435
  schemaSha: z.ZodString;
432
436
  sourcesSha: z.ZodString;
433
- commitSha: z.ZodString;
437
+ commitSha: z.ZodOptional<z.ZodString>;
434
438
  patches: z.ZodArray<z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>>;
435
439
  appliedPatches: z.ZodOptional<z.ZodArray<z.ZodString & z.ZodType<import("@valbuild/core").PatchId, string, z.core.$ZodTypeInternals<import("@valbuild/core").PatchId, string>>>>;
436
440
  headCommitSha: z.ZodOptional<z.ZodString>;
437
441
  commits: z.ZodArray<z.ZodObject<{
438
442
  commitSha: z.ZodString;
439
- clientCommitSha: z.ZodString;
440
- parentCommitSha: z.ZodString;
443
+ clientCommitSha: z.ZodNullable<z.ZodString>;
444
+ parentCommitSha: z.ZodNullable<z.ZodString>;
441
445
  branch: z.ZodString;
442
446
  creator: z.ZodString;
443
447
  createdAt: z.ZodString;
@@ -462,6 +466,10 @@ export declare const Api: {
462
466
  }, z.core.$strip>;
463
467
  profileId: z.ZodNullable<z.ZodString>;
464
468
  mode: z.ZodUnion<readonly [z.ZodLiteral<"http">, z.ZodLiteral<"fs">]>;
469
+ publishRefusal: z.ZodOptional<z.ZodObject<{
470
+ code: z.ZodLiteral<"no-base">;
471
+ message: z.ZodString;
472
+ }, z.core.$strip>>;
465
473
  }, z.core.$strip>]>;
466
474
  }, z.core.$strip>]>;
467
475
  };
@@ -948,7 +956,7 @@ export declare const Api: {
948
956
  message: z.ZodString;
949
957
  value: z.ZodOptional<z.ZodUnknown>;
950
958
  fatal: z.ZodOptional<z.ZodBoolean>;
951
- fixes: z.ZodOptional<z.ZodArray<z.ZodType<"image:add-metadata" | "image:check-metadata" | "image:upload-remote" | "image:download-remote" | "image:check-remote" | "images:check-remote" | "images:upload-remote" | "file:add-metadata" | "file:check-metadata" | "file:upload-remote" | "file:download-remote" | "file:check-remote" | "files:check-remote" | "files:upload-remote" | "keyof:check-keys" | "router:check-route" | "locale:check-locale" | "images:check-unique-folder" | "files:check-unique-folder" | "images:check-all-files" | "files:check-all-files" | "jsonValues:extract-entry" | "record:fill-keys" | "external:upload", unknown, z.core.$ZodTypeInternals<"image:add-metadata" | "image:check-metadata" | "image:upload-remote" | "image:download-remote" | "image:check-remote" | "images:check-remote" | "images:upload-remote" | "file:add-metadata" | "file:check-metadata" | "file:upload-remote" | "file:download-remote" | "file:check-remote" | "files:check-remote" | "files:upload-remote" | "keyof:check-keys" | "router:check-route" | "locale:check-locale" | "images:check-unique-folder" | "files:check-unique-folder" | "images:check-all-files" | "files:check-all-files" | "jsonValues:extract-entry" | "record:fill-keys" | "external:upload", unknown>>>>;
959
+ fixes: z.ZodOptional<z.ZodArray<z.ZodType<"image:add-metadata" | "image:check-metadata" | "image:upload-remote" | "image:download-remote" | "image:check-remote" | "images:check-remote" | "images:upload-remote" | "file:add-metadata" | "file:check-metadata" | "file:upload-remote" | "file:download-remote" | "file:check-remote" | "files:check-remote" | "files:upload-remote" | "keyof:check-keys" | "router:check-route" | "locale:check-locale" | "images:check-unique-folder" | "files:check-unique-folder" | "images:check-all-files" | "files:check-all-files" | "jsonValues:extract-entry" | "record:fill-keys" | "external:upload" | "view:check-module", unknown, z.core.$ZodTypeInternals<"image:add-metadata" | "image:check-metadata" | "image:upload-remote" | "image:download-remote" | "image:check-remote" | "images:check-remote" | "images:upload-remote" | "file:add-metadata" | "file:check-metadata" | "file:upload-remote" | "file:download-remote" | "file:check-remote" | "files:check-remote" | "files:upload-remote" | "keyof:check-keys" | "router:check-route" | "locale:check-locale" | "images:check-unique-folder" | "files:check-unique-folder" | "images:check-all-files" | "files:check-all-files" | "jsonValues:extract-entry" | "record:fill-keys" | "external:upload" | "view:check-module", unknown>>>>;
952
960
  }, z.core.$strip>>>>;
953
961
  }, z.core.$strip>>;
954
962
  }, z.core.$strip>;
@@ -1029,6 +1037,12 @@ export declare const Api: {
1029
1037
  status: z.ZodLiteral<409>;
1030
1038
  json: z.ZodUnion<readonly [z.ZodObject<{
1031
1039
  message: z.ZodString;
1040
+ publishRefusal: z.ZodObject<{
1041
+ code: z.ZodLiteral<"no-base">;
1042
+ message: z.ZodString;
1043
+ }, z.core.$strip>;
1044
+ }, z.core.$strip>, z.ZodObject<{
1045
+ message: z.ZodString;
1032
1046
  }, z.core.$strip>, z.ZodObject<{
1033
1047
  message: z.ZodString;
1034
1048
  isNotFastForward: z.ZodLiteral<true>;
@@ -1106,8 +1120,8 @@ export declare const Api: {
1106
1120
  json: z.ZodObject<{
1107
1121
  commits: z.ZodArray<z.ZodObject<{
1108
1122
  commitSha: z.ZodString;
1109
- parentCommitSha: z.ZodString;
1110
- clientCommitSha: z.ZodString;
1123
+ parentCommitSha: z.ZodNullable<z.ZodString>;
1124
+ clientCommitSha: z.ZodNullable<z.ZodString>;
1111
1125
  branch: z.ZodString;
1112
1126
  createdBranch: z.ZodNullable<z.ZodString>;
1113
1127
  creator: z.ZodNullable<z.ZodString>;
@@ -1164,8 +1178,8 @@ export declare const Api: {
1164
1178
  json: z.ZodObject<{
1165
1179
  commit: z.ZodObject<{
1166
1180
  commitSha: z.ZodString;
1167
- parentCommitSha: z.ZodString;
1168
- clientCommitSha: z.ZodString;
1181
+ parentCommitSha: z.ZodNullable<z.ZodString>;
1182
+ clientCommitSha: z.ZodNullable<z.ZodString>;
1169
1183
  branch: z.ZodString;
1170
1184
  createdBranch: z.ZodNullable<z.ZodString>;
1171
1185
  creator: z.ZodNullable<z.ZodString>;
@@ -40,8 +40,8 @@ export declare const HistoryError: z.ZodDiscriminatedUnion<[z.ZodObject<{
40
40
  export type HistoryError = z.infer<typeof HistoryError>;
41
41
  export declare const HistoricalCommit: z.ZodObject<{
42
42
  commitSha: z.ZodString;
43
- parentCommitSha: z.ZodString;
44
- clientCommitSha: z.ZodString;
43
+ parentCommitSha: z.ZodNullable<z.ZodString>;
44
+ clientCommitSha: z.ZodNullable<z.ZodString>;
45
45
  branch: z.ZodString;
46
46
  createdBranch: z.ZodNullable<z.ZodString>;
47
47
  creator: z.ZodNullable<z.ZodString>;
@@ -97,8 +97,8 @@ export type HistoricalModule = z.infer<typeof HistoricalModule>;
97
97
  export declare const HistoricalPatchSet: z.ZodObject<{
98
98
  commit: z.ZodObject<{
99
99
  commitSha: z.ZodString;
100
- parentCommitSha: z.ZodString;
101
- clientCommitSha: z.ZodString;
100
+ parentCommitSha: z.ZodNullable<z.ZodString>;
101
+ clientCommitSha: z.ZodNullable<z.ZodString>;
102
102
  branch: z.ZodString;
103
103
  createdBranch: z.ZodNullable<z.ZodString>;
104
104
  creator: z.ZodNullable<z.ZodString>;
@@ -76,4 +76,23 @@ export declare const SerializedCodeSchema: z.ZodType<SerializedCodeSchemaT>;
76
76
  export declare const SerializedLocaleSchema: z.ZodType<SerializedLocaleSchemaT>;
77
77
  export declare const SerializedRouteSchema: z.ZodType<SerializedRouteSchemaT>;
78
78
  export declare const SerializedSettingsSchema: z.ZodType<SerializedSettingsSchemaT>;
79
+ /**
80
+ * A view field shows another module and stores nothing of its own.
81
+ *
82
+ * Nothing in the type system forces this member to exist: `SerializedSchema` is
83
+ * declared as `z.ZodType<SerializedSchemaT>`, so a missing member is not a type
84
+ * error — it is a runtime parse failure of the WHOLE module's schema, since the
85
+ * containing object fails with it.
86
+ */
87
+ export declare const SerializedValViewSchema: z.ZodObject<{
88
+ type: z.ZodLiteral<"view">;
89
+ render: z.ZodOptional<z.ZodOptional<z.ZodObject<{
90
+ as: z.ZodLiteral<"inline">;
91
+ }, z.core.$strip>>>;
92
+ moduleFilePath: z.ZodType<import("@valbuild/core").ModuleFilePath, unknown, z.core.$ZodTypeInternals<import("@valbuild/core").ModuleFilePath, unknown>>;
93
+ opt: z.ZodLiteral<false>;
94
+ readonly: z.ZodOptional<z.ZodBoolean>;
95
+ hidden: z.ZodOptional<z.ZodBoolean>;
96
+ description: z.ZodOptional<z.ZodString>;
97
+ }, z.core.$strip>;
79
98
  export declare const SerializedSchema: z.ZodType<SerializedSchemaT>;
@@ -1,8 +1,8 @@
1
1
  import { z } from "zod";
2
2
  export declare const ValCommit: z.ZodObject<{
3
3
  commitSha: z.ZodString;
4
- clientCommitSha: z.ZodString;
5
- parentCommitSha: z.ZodString;
4
+ clientCommitSha: z.ZodNullable<z.ZodString>;
5
+ parentCommitSha: z.ZodNullable<z.ZodString>;
6
6
  branch: z.ZodString;
7
7
  creator: z.ZodString;
8
8
  createdAt: z.ZodString;
@@ -923,6 +923,10 @@ var SourcePath = zod.z.string().transform(function (path) {
923
923
  return path;
924
924
  });
925
925
 
926
+ var ModuleFilePath$1 = zod.z.string().transform(function (path) {
927
+ return path;
928
+ });
929
+
926
930
  var _excluded = ["directory"];
927
931
 
928
932
  // A render is static config, so unlike a `preview` it travels WHOLE — this
@@ -1216,12 +1220,38 @@ var SerializedSettingsSchema = zod.z.lazy(function () {
1216
1220
  section: zod.z.string().optional()
1217
1221
  }));
1218
1222
  });
1219
- var SerializedSchema = zod.z.union([SerializedStringSchema, SerializedLiteralSchema, SerializedBooleanSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedArraySchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedRichTextSchema, SerializedRecordSchema, SerializedKeyOfSchema, SerializedRouteSchema, SerializedLocaleSchema, SerializedFileSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedColorSchema, SerializedCodeSchema, SerializedSettingsSchema, SerializedImageSchema]);
1223
+
1224
+ /**
1225
+ * A view field shows another module and stores nothing of its own.
1226
+ *
1227
+ * Nothing in the type system forces this member to exist: `SerializedSchema` is
1228
+ * declared as `z.ZodType<SerializedSchemaT>`, so a missing member is not a type
1229
+ * error — it is a runtime parse failure of the WHOLE module's schema, since the
1230
+ * containing object fails with it.
1231
+ */
1232
+ var SerializedValViewSchema = zod.z.object({
1233
+ type: zod.z.literal("view"),
1234
+ render: FieldRender.optional(),
1235
+ moduleFilePath: ModuleFilePath$1,
1236
+ opt: zod.z.literal(false),
1237
+ readonly: zod.z["boolean"]().optional(),
1238
+ hidden: zod.z["boolean"]().optional(),
1239
+ description: zod.z.string().optional()
1240
+ });
1241
+ var SerializedSchema = zod.z.union([SerializedStringSchema, SerializedLiteralSchema, SerializedBooleanSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedArraySchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedRichTextSchema, SerializedRecordSchema, SerializedKeyOfSchema, SerializedRouteSchema, SerializedLocaleSchema, SerializedFileSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedColorSchema, SerializedCodeSchema, SerializedSettingsSchema, SerializedImageSchema, SerializedValViewSchema]);
1220
1242
 
1221
1243
  var ValCommit = zod.z.object({
1222
1244
  commitSha: zod.z.string(),
1223
- clientCommitSha: zod.z.string(),
1224
- parentCommitSha: zod.z.string(),
1245
+ /**
1246
+ * Where the publisher said it was, or `null` when it did not say.
1247
+ *
1248
+ * Nullable since the content service mints its own commit shas rather than
1249
+ * taking git's: most publishers no longer bake a commit at all, and a root
1250
+ * commit -- the first publish of a project with no repository -- has no
1251
+ * parent for the same reason.
1252
+ */
1253
+ clientCommitSha: zod.z.string().nullable(),
1254
+ parentCommitSha: zod.z.string().nullable(),
1225
1255
  branch: zod.z.string(),
1226
1256
  creator: zod.z.string(),
1227
1257
  createdAt: zod.z.string(),
@@ -1293,8 +1323,10 @@ var HistoryError = zod.z.discriminatedUnion("kind", [zod.z.object({
1293
1323
  })]);
1294
1324
  var HistoricalCommit = zod.z.object({
1295
1325
  commitSha: zod.z.string(),
1296
- parentCommitSha: zod.z.string(),
1297
- clientCommitSha: zod.z.string(),
1326
+ /** `null` for a root commit. See `ValCommit`. */
1327
+ parentCommitSha: zod.z.string().nullable(),
1328
+ /** `null` when the publisher did not say where it was. See `ValCommit`. */
1329
+ clientCommitSha: zod.z.string().nullable(),
1298
1330
  branch: zod.z.string(),
1299
1331
  createdBranch: zod.z.string().nullable(),
1300
1332
  creator: zod.z.string().nullable(),
@@ -1392,7 +1424,7 @@ var ValConfig = zod.z.object({
1392
1424
  gitCommit: zod.z.string().optional(),
1393
1425
  gitBranch: zod.z.string().optional()
1394
1426
  });
1395
- var ValidationFixZ = zod.z.union([zod.z.literal("image:add-metadata"), zod.z.literal("image:check-metadata"), zod.z.literal("image:check-remote"), zod.z.literal("image:upload-remote"), zod.z.literal("image:download-remote"), zod.z.literal("images:check-remote"), zod.z.literal("images:upload-remote"), zod.z.literal("file:add-metadata"), zod.z.literal("file:check-metadata"), zod.z.literal("file:check-remote"), zod.z.literal("file:upload-remote"), zod.z.literal("file:download-remote"), zod.z.literal("files:check-remote"), zod.z.literal("files:upload-remote"), zod.z.literal("keyof:check-keys"), zod.z.literal("router:check-route"), zod.z.literal("locale:check-locale"), zod.z.literal("record:fill-keys"), zod.z.literal("images:check-unique-folder"), zod.z.literal("files:check-unique-folder"), zod.z.literal("images:check-all-files"), zod.z.literal("files:check-all-files"), zod.z.literal("jsonValues:extract-entry")]);
1427
+ var ValidationFixZ = zod.z.union([zod.z.literal("image:add-metadata"), zod.z.literal("image:check-metadata"), zod.z.literal("image:check-remote"), zod.z.literal("image:upload-remote"), zod.z.literal("image:download-remote"), zod.z.literal("images:check-remote"), zod.z.literal("images:upload-remote"), zod.z.literal("file:add-metadata"), zod.z.literal("file:check-metadata"), zod.z.literal("file:check-remote"), zod.z.literal("file:upload-remote"), zod.z.literal("file:download-remote"), zod.z.literal("files:check-remote"), zod.z.literal("files:upload-remote"), zod.z.literal("keyof:check-keys"), zod.z.literal("router:check-route"), zod.z.literal("locale:check-locale"), zod.z.literal("record:fill-keys"), zod.z.literal("images:check-unique-folder"), zod.z.literal("files:check-unique-folder"), zod.z.literal("images:check-all-files"), zod.z.literal("files:check-all-files"), zod.z.literal("jsonValues:extract-entry"), zod.z.literal("view:check-module")]);
1396
1428
  var ValidationError = zod.z.object({
1397
1429
  message: zod.z.string(),
1398
1430
  value: zod.z.unknown().optional(),
@@ -1415,6 +1447,27 @@ var GenericError = zod.z.object({
1415
1447
  message: zod.z.string()
1416
1448
  });
1417
1449
 
1450
+ /**
1451
+ * Why a publish cannot happen, in a form the Studio can show.
1452
+ *
1453
+ * Carried on `/stat` so the action is disabled with the reason beside it, and
1454
+ * on `/save`'s 409 so the same answer is given to a client that asked anyway --
1455
+ * a stat can be a poll out of date, and nothing may reach the commit path on a
1456
+ * project this deployment cannot publish.
1457
+ *
1458
+ * `no-base` is the only code so far: there is nowhere for this publish's
1459
+ * commit to be based. Note which way round that is. A project whose content
1460
+ * service is the store of record always HAS a base -- the service's own chain,
1461
+ * which mints its own shas -- so this is not about a missing git repository.
1462
+ * It is about a deployment that cannot do what its project requires: one built
1463
+ * before the project attached a repository, now asked to mirror commits into
1464
+ * one it knows no commit for.
1465
+ */
1466
+ var PublishRefusal = zod.z.object({
1467
+ code: zod.z.literal("no-base"),
1468
+ message: zod.z.string()
1469
+ });
1470
+
1418
1471
  /**
1419
1472
  * A patch group: the set of patches one user has chosen to publish.
1420
1473
  *
@@ -1810,7 +1863,8 @@ var Api = {
1810
1863
  config: ValConfig,
1811
1864
  profileId: zod.z.string().nullable(),
1812
1865
  mode: zod.z.union([zod.z.literal("http"), zod.z.literal("fs")]),
1813
- jsonEntriesSha: zod.z.string().optional()
1866
+ jsonEntriesSha: zod.z.string().optional(),
1867
+ publishRefusal: PublishRefusal.optional()
1814
1868
  }), zod.z.object({
1815
1869
  type: zod.z.literal("use-websocket"),
1816
1870
  url: zod.z.string(),
@@ -1818,7 +1872,16 @@ var Api = {
1818
1872
  baseSha: zod.z.string(),
1819
1873
  schemaSha: zod.z.string(),
1820
1874
  sourcesSha: zod.z.string(),
1821
- commitSha: zod.z.string(),
1875
+ /**
1876
+ * The commit this deployment was built from.
1877
+ *
1878
+ * Optional: a project whose content service is the store of
1879
+ * record has no repository and no commit baked into its build.
1880
+ * The Studio has always parsed this as optional -- see
1881
+ * `useStatus` -- and shows a branch and a commit only when there
1882
+ * is one.
1883
+ */
1884
+ commitSha: zod.z.string().optional(),
1822
1885
  patches: zod.z.array(PatchId),
1823
1886
  /**
1824
1887
  * Of `patches`, the ones that have already SHIPPED.
@@ -1862,7 +1925,8 @@ var Api = {
1862
1925
  deployments: zod.z.array(ValDeployment).optional(),
1863
1926
  config: ValConfig,
1864
1927
  profileId: zod.z.string().nullable(),
1865
- mode: zod.z.union([zod.z.literal("http"), zod.z.literal("fs")])
1928
+ mode: zod.z.union([zod.z.literal("http"), zod.z.literal("fs")]),
1929
+ publishRefusal: PublishRefusal.optional()
1866
1930
  })])
1867
1931
  })])
1868
1932
  }
@@ -2383,7 +2447,19 @@ var Api = {
2383
2447
  json: GenericError
2384
2448
  }), zod.z.object({
2385
2449
  status: zod.z.literal(409),
2386
- json: zod.z.union([/** A group that has already shipped. See the 403 above. */
2450
+ json: zod.z.union([
2451
+ /*
2452
+ * This deployment cannot publish this project at all.
2453
+ *
2454
+ * First in the union so it is read before the bare
2455
+ * `{ message }` above it would swallow it. `/stat` carries the
2456
+ * same refusal, so a Studio that is up to date never sends a save
2457
+ * that lands here -- this is for the one that is a poll behind.
2458
+ */
2459
+ zod.z.object({
2460
+ message: zod.z.string(),
2461
+ publishRefusal: PublishRefusal
2462
+ }), /** A group that has already shipped. See the 403 above. */
2387
2463
  zod.z.object({
2388
2464
  message: zod.z.string()
2389
2465
  }), zod.z.object({
@@ -4697,6 +4773,13 @@ function emptyOf(schema, context) {
4697
4773
  }, (_schema$options$forma = (_schema$options = schema.options) === null || _schema$options === void 0 ? void 0 : _schema$options.format) !== null && _schema$options$forma !== void 0 ? _schema$options$forma : core.DEFAULT_COLOR_FORMAT);
4698
4774
  } else if (schema.type === "code") {
4699
4775
  return ""; // An empty editor: no language has a sensible starting snippet
4776
+ } else if (schema.type === "view") {
4777
+ // The pointer IS the empty value: a view has exactly one valid source, and
4778
+ // the schema knows it. A new page with a view field gets the same pointer
4779
+ // every other page's has.
4780
+ return {
4781
+ view: schema.moduleFilePath
4782
+ };
4700
4783
  }
4701
4784
  var _exhaustiveCheck = schema;
4702
4785
  throw Error("Unexpected schema type: " + JSON.stringify(_exhaustiveCheck));
@@ -5344,6 +5427,8 @@ function isSkippableFixCode(fix) {
5344
5427
  case "files:check-unique-folder":
5345
5428
  case "images:check-all-files":
5346
5429
  case "files:check-all-files":
5430
+ case "view:check-module":
5431
+ // schema is code: nothing for an editor to do
5347
5432
  return true;
5348
5433
  case "keyof:check-keys":
5349
5434
  case "router:check-route":
@@ -5825,6 +5910,12 @@ function traverseSchemaSource(source, schema, path, callback) {
5825
5910
  }
5826
5911
  return;
5827
5912
  }
5913
+ if (schema.type === "view") {
5914
+ // The source here is a pointer — a module file path, not content. Indexing
5915
+ // it would make every view a hit for its target's filename, and the target
5916
+ // is already indexed under its own path.
5917
+ return;
5918
+ }
5828
5919
 
5829
5920
  // Exhaustive check
5830
5921
  var exhaustiveCheck = schema;
@@ -6706,6 +6797,7 @@ exports.SerializedRouteSchema = SerializedRouteSchema;
6706
6797
  exports.SerializedSchema = SerializedSchema;
6707
6798
  exports.SerializedSettingsSchema = SerializedSettingsSchema;
6708
6799
  exports.SerializedStringSchema = SerializedStringSchema;
6800
+ exports.SerializedValViewSchema = SerializedValViewSchema;
6709
6801
  exports.SharedValConfig = SharedValConfig;
6710
6802
  exports.VAL_ENABLE_COOKIE_NAME = VAL_ENABLE_COOKIE_NAME;
6711
6803
  exports.VAL_GREEN_RAMP = VAL_GREEN_RAMP;
@@ -923,6 +923,10 @@ var SourcePath = zod.z.string().transform(function (path) {
923
923
  return path;
924
924
  });
925
925
 
926
+ var ModuleFilePath$1 = zod.z.string().transform(function (path) {
927
+ return path;
928
+ });
929
+
926
930
  var _excluded = ["directory"];
927
931
 
928
932
  // A render is static config, so unlike a `preview` it travels WHOLE — this
@@ -1216,12 +1220,38 @@ var SerializedSettingsSchema = zod.z.lazy(function () {
1216
1220
  section: zod.z.string().optional()
1217
1221
  }));
1218
1222
  });
1219
- var SerializedSchema = zod.z.union([SerializedStringSchema, SerializedLiteralSchema, SerializedBooleanSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedArraySchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedRichTextSchema, SerializedRecordSchema, SerializedKeyOfSchema, SerializedRouteSchema, SerializedLocaleSchema, SerializedFileSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedColorSchema, SerializedCodeSchema, SerializedSettingsSchema, SerializedImageSchema]);
1223
+
1224
+ /**
1225
+ * A view field shows another module and stores nothing of its own.
1226
+ *
1227
+ * Nothing in the type system forces this member to exist: `SerializedSchema` is
1228
+ * declared as `z.ZodType<SerializedSchemaT>`, so a missing member is not a type
1229
+ * error — it is a runtime parse failure of the WHOLE module's schema, since the
1230
+ * containing object fails with it.
1231
+ */
1232
+ var SerializedValViewSchema = zod.z.object({
1233
+ type: zod.z.literal("view"),
1234
+ render: FieldRender.optional(),
1235
+ moduleFilePath: ModuleFilePath$1,
1236
+ opt: zod.z.literal(false),
1237
+ readonly: zod.z["boolean"]().optional(),
1238
+ hidden: zod.z["boolean"]().optional(),
1239
+ description: zod.z.string().optional()
1240
+ });
1241
+ var SerializedSchema = zod.z.union([SerializedStringSchema, SerializedLiteralSchema, SerializedBooleanSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedArraySchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedRichTextSchema, SerializedRecordSchema, SerializedKeyOfSchema, SerializedRouteSchema, SerializedLocaleSchema, SerializedFileSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedColorSchema, SerializedCodeSchema, SerializedSettingsSchema, SerializedImageSchema, SerializedValViewSchema]);
1220
1242
 
1221
1243
  var ValCommit = zod.z.object({
1222
1244
  commitSha: zod.z.string(),
1223
- clientCommitSha: zod.z.string(),
1224
- parentCommitSha: zod.z.string(),
1245
+ /**
1246
+ * Where the publisher said it was, or `null` when it did not say.
1247
+ *
1248
+ * Nullable since the content service mints its own commit shas rather than
1249
+ * taking git's: most publishers no longer bake a commit at all, and a root
1250
+ * commit -- the first publish of a project with no repository -- has no
1251
+ * parent for the same reason.
1252
+ */
1253
+ clientCommitSha: zod.z.string().nullable(),
1254
+ parentCommitSha: zod.z.string().nullable(),
1225
1255
  branch: zod.z.string(),
1226
1256
  creator: zod.z.string(),
1227
1257
  createdAt: zod.z.string(),
@@ -1293,8 +1323,10 @@ var HistoryError = zod.z.discriminatedUnion("kind", [zod.z.object({
1293
1323
  })]);
1294
1324
  var HistoricalCommit = zod.z.object({
1295
1325
  commitSha: zod.z.string(),
1296
- parentCommitSha: zod.z.string(),
1297
- clientCommitSha: zod.z.string(),
1326
+ /** `null` for a root commit. See `ValCommit`. */
1327
+ parentCommitSha: zod.z.string().nullable(),
1328
+ /** `null` when the publisher did not say where it was. See `ValCommit`. */
1329
+ clientCommitSha: zod.z.string().nullable(),
1298
1330
  branch: zod.z.string(),
1299
1331
  createdBranch: zod.z.string().nullable(),
1300
1332
  creator: zod.z.string().nullable(),
@@ -1392,7 +1424,7 @@ var ValConfig = zod.z.object({
1392
1424
  gitCommit: zod.z.string().optional(),
1393
1425
  gitBranch: zod.z.string().optional()
1394
1426
  });
1395
- var ValidationFixZ = zod.z.union([zod.z.literal("image:add-metadata"), zod.z.literal("image:check-metadata"), zod.z.literal("image:check-remote"), zod.z.literal("image:upload-remote"), zod.z.literal("image:download-remote"), zod.z.literal("images:check-remote"), zod.z.literal("images:upload-remote"), zod.z.literal("file:add-metadata"), zod.z.literal("file:check-metadata"), zod.z.literal("file:check-remote"), zod.z.literal("file:upload-remote"), zod.z.literal("file:download-remote"), zod.z.literal("files:check-remote"), zod.z.literal("files:upload-remote"), zod.z.literal("keyof:check-keys"), zod.z.literal("router:check-route"), zod.z.literal("locale:check-locale"), zod.z.literal("record:fill-keys"), zod.z.literal("images:check-unique-folder"), zod.z.literal("files:check-unique-folder"), zod.z.literal("images:check-all-files"), zod.z.literal("files:check-all-files"), zod.z.literal("jsonValues:extract-entry")]);
1427
+ var ValidationFixZ = zod.z.union([zod.z.literal("image:add-metadata"), zod.z.literal("image:check-metadata"), zod.z.literal("image:check-remote"), zod.z.literal("image:upload-remote"), zod.z.literal("image:download-remote"), zod.z.literal("images:check-remote"), zod.z.literal("images:upload-remote"), zod.z.literal("file:add-metadata"), zod.z.literal("file:check-metadata"), zod.z.literal("file:check-remote"), zod.z.literal("file:upload-remote"), zod.z.literal("file:download-remote"), zod.z.literal("files:check-remote"), zod.z.literal("files:upload-remote"), zod.z.literal("keyof:check-keys"), zod.z.literal("router:check-route"), zod.z.literal("locale:check-locale"), zod.z.literal("record:fill-keys"), zod.z.literal("images:check-unique-folder"), zod.z.literal("files:check-unique-folder"), zod.z.literal("images:check-all-files"), zod.z.literal("files:check-all-files"), zod.z.literal("jsonValues:extract-entry"), zod.z.literal("view:check-module")]);
1396
1428
  var ValidationError = zod.z.object({
1397
1429
  message: zod.z.string(),
1398
1430
  value: zod.z.unknown().optional(),
@@ -1415,6 +1447,27 @@ var GenericError = zod.z.object({
1415
1447
  message: zod.z.string()
1416
1448
  });
1417
1449
 
1450
+ /**
1451
+ * Why a publish cannot happen, in a form the Studio can show.
1452
+ *
1453
+ * Carried on `/stat` so the action is disabled with the reason beside it, and
1454
+ * on `/save`'s 409 so the same answer is given to a client that asked anyway --
1455
+ * a stat can be a poll out of date, and nothing may reach the commit path on a
1456
+ * project this deployment cannot publish.
1457
+ *
1458
+ * `no-base` is the only code so far: there is nowhere for this publish's
1459
+ * commit to be based. Note which way round that is. A project whose content
1460
+ * service is the store of record always HAS a base -- the service's own chain,
1461
+ * which mints its own shas -- so this is not about a missing git repository.
1462
+ * It is about a deployment that cannot do what its project requires: one built
1463
+ * before the project attached a repository, now asked to mirror commits into
1464
+ * one it knows no commit for.
1465
+ */
1466
+ var PublishRefusal = zod.z.object({
1467
+ code: zod.z.literal("no-base"),
1468
+ message: zod.z.string()
1469
+ });
1470
+
1418
1471
  /**
1419
1472
  * A patch group: the set of patches one user has chosen to publish.
1420
1473
  *
@@ -1810,7 +1863,8 @@ var Api = {
1810
1863
  config: ValConfig,
1811
1864
  profileId: zod.z.string().nullable(),
1812
1865
  mode: zod.z.union([zod.z.literal("http"), zod.z.literal("fs")]),
1813
- jsonEntriesSha: zod.z.string().optional()
1866
+ jsonEntriesSha: zod.z.string().optional(),
1867
+ publishRefusal: PublishRefusal.optional()
1814
1868
  }), zod.z.object({
1815
1869
  type: zod.z.literal("use-websocket"),
1816
1870
  url: zod.z.string(),
@@ -1818,7 +1872,16 @@ var Api = {
1818
1872
  baseSha: zod.z.string(),
1819
1873
  schemaSha: zod.z.string(),
1820
1874
  sourcesSha: zod.z.string(),
1821
- commitSha: zod.z.string(),
1875
+ /**
1876
+ * The commit this deployment was built from.
1877
+ *
1878
+ * Optional: a project whose content service is the store of
1879
+ * record has no repository and no commit baked into its build.
1880
+ * The Studio has always parsed this as optional -- see
1881
+ * `useStatus` -- and shows a branch and a commit only when there
1882
+ * is one.
1883
+ */
1884
+ commitSha: zod.z.string().optional(),
1822
1885
  patches: zod.z.array(PatchId),
1823
1886
  /**
1824
1887
  * Of `patches`, the ones that have already SHIPPED.
@@ -1862,7 +1925,8 @@ var Api = {
1862
1925
  deployments: zod.z.array(ValDeployment).optional(),
1863
1926
  config: ValConfig,
1864
1927
  profileId: zod.z.string().nullable(),
1865
- mode: zod.z.union([zod.z.literal("http"), zod.z.literal("fs")])
1928
+ mode: zod.z.union([zod.z.literal("http"), zod.z.literal("fs")]),
1929
+ publishRefusal: PublishRefusal.optional()
1866
1930
  })])
1867
1931
  })])
1868
1932
  }
@@ -2383,7 +2447,19 @@ var Api = {
2383
2447
  json: GenericError
2384
2448
  }), zod.z.object({
2385
2449
  status: zod.z.literal(409),
2386
- json: zod.z.union([/** A group that has already shipped. See the 403 above. */
2450
+ json: zod.z.union([
2451
+ /*
2452
+ * This deployment cannot publish this project at all.
2453
+ *
2454
+ * First in the union so it is read before the bare
2455
+ * `{ message }` above it would swallow it. `/stat` carries the
2456
+ * same refusal, so a Studio that is up to date never sends a save
2457
+ * that lands here -- this is for the one that is a poll behind.
2458
+ */
2459
+ zod.z.object({
2460
+ message: zod.z.string(),
2461
+ publishRefusal: PublishRefusal
2462
+ }), /** A group that has already shipped. See the 403 above. */
2387
2463
  zod.z.object({
2388
2464
  message: zod.z.string()
2389
2465
  }), zod.z.object({
@@ -4697,6 +4773,13 @@ function emptyOf(schema, context) {
4697
4773
  }, (_schema$options$forma = (_schema$options = schema.options) === null || _schema$options === void 0 ? void 0 : _schema$options.format) !== null && _schema$options$forma !== void 0 ? _schema$options$forma : core.DEFAULT_COLOR_FORMAT);
4698
4774
  } else if (schema.type === "code") {
4699
4775
  return ""; // An empty editor: no language has a sensible starting snippet
4776
+ } else if (schema.type === "view") {
4777
+ // The pointer IS the empty value: a view has exactly one valid source, and
4778
+ // the schema knows it. A new page with a view field gets the same pointer
4779
+ // every other page's has.
4780
+ return {
4781
+ view: schema.moduleFilePath
4782
+ };
4700
4783
  }
4701
4784
  var _exhaustiveCheck = schema;
4702
4785
  throw Error("Unexpected schema type: " + JSON.stringify(_exhaustiveCheck));
@@ -5344,6 +5427,8 @@ function isSkippableFixCode(fix) {
5344
5427
  case "files:check-unique-folder":
5345
5428
  case "images:check-all-files":
5346
5429
  case "files:check-all-files":
5430
+ case "view:check-module":
5431
+ // schema is code: nothing for an editor to do
5347
5432
  return true;
5348
5433
  case "keyof:check-keys":
5349
5434
  case "router:check-route":
@@ -5825,6 +5910,12 @@ function traverseSchemaSource(source, schema, path, callback) {
5825
5910
  }
5826
5911
  return;
5827
5912
  }
5913
+ if (schema.type === "view") {
5914
+ // The source here is a pointer — a module file path, not content. Indexing
5915
+ // it would make every view a hit for its target's filename, and the target
5916
+ // is already indexed under its own path.
5917
+ return;
5918
+ }
5828
5919
 
5829
5920
  // Exhaustive check
5830
5921
  var exhaustiveCheck = schema;
@@ -6706,6 +6797,7 @@ exports.SerializedRouteSchema = SerializedRouteSchema;
6706
6797
  exports.SerializedSchema = SerializedSchema;
6707
6798
  exports.SerializedSettingsSchema = SerializedSettingsSchema;
6708
6799
  exports.SerializedStringSchema = SerializedStringSchema;
6800
+ exports.SerializedValViewSchema = SerializedValViewSchema;
6709
6801
  exports.SharedValConfig = SharedValConfig;
6710
6802
  exports.VAL_ENABLE_COOKIE_NAME = VAL_ENABLE_COOKIE_NAME;
6711
6803
  exports.VAL_GREEN_RAMP = VAL_GREEN_RAMP;
@@ -916,6 +916,10 @@ var SourcePath = z.string().transform(function (path) {
916
916
  return path;
917
917
  });
918
918
 
919
+ var ModuleFilePath$1 = z.string().transform(function (path) {
920
+ return path;
921
+ });
922
+
919
923
  var _excluded = ["directory"];
920
924
 
921
925
  // A render is static config, so unlike a `preview` it travels WHOLE — this
@@ -1209,12 +1213,38 @@ var SerializedSettingsSchema = z.lazy(function () {
1209
1213
  section: z.string().optional()
1210
1214
  }));
1211
1215
  });
1212
- var SerializedSchema = z.union([SerializedStringSchema, SerializedLiteralSchema, SerializedBooleanSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedArraySchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedRichTextSchema, SerializedRecordSchema, SerializedKeyOfSchema, SerializedRouteSchema, SerializedLocaleSchema, SerializedFileSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedColorSchema, SerializedCodeSchema, SerializedSettingsSchema, SerializedImageSchema]);
1216
+
1217
+ /**
1218
+ * A view field shows another module and stores nothing of its own.
1219
+ *
1220
+ * Nothing in the type system forces this member to exist: `SerializedSchema` is
1221
+ * declared as `z.ZodType<SerializedSchemaT>`, so a missing member is not a type
1222
+ * error — it is a runtime parse failure of the WHOLE module's schema, since the
1223
+ * containing object fails with it.
1224
+ */
1225
+ var SerializedValViewSchema = z.object({
1226
+ type: z.literal("view"),
1227
+ render: FieldRender.optional(),
1228
+ moduleFilePath: ModuleFilePath$1,
1229
+ opt: z.literal(false),
1230
+ readonly: z["boolean"]().optional(),
1231
+ hidden: z["boolean"]().optional(),
1232
+ description: z.string().optional()
1233
+ });
1234
+ var SerializedSchema = z.union([SerializedStringSchema, SerializedLiteralSchema, SerializedBooleanSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedArraySchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedRichTextSchema, SerializedRecordSchema, SerializedKeyOfSchema, SerializedRouteSchema, SerializedLocaleSchema, SerializedFileSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedColorSchema, SerializedCodeSchema, SerializedSettingsSchema, SerializedImageSchema, SerializedValViewSchema]);
1213
1235
 
1214
1236
  var ValCommit = z.object({
1215
1237
  commitSha: z.string(),
1216
- clientCommitSha: z.string(),
1217
- parentCommitSha: z.string(),
1238
+ /**
1239
+ * Where the publisher said it was, or `null` when it did not say.
1240
+ *
1241
+ * Nullable since the content service mints its own commit shas rather than
1242
+ * taking git's: most publishers no longer bake a commit at all, and a root
1243
+ * commit -- the first publish of a project with no repository -- has no
1244
+ * parent for the same reason.
1245
+ */
1246
+ clientCommitSha: z.string().nullable(),
1247
+ parentCommitSha: z.string().nullable(),
1218
1248
  branch: z.string(),
1219
1249
  creator: z.string(),
1220
1250
  createdAt: z.string(),
@@ -1286,8 +1316,10 @@ var HistoryError = z.discriminatedUnion("kind", [z.object({
1286
1316
  })]);
1287
1317
  var HistoricalCommit = z.object({
1288
1318
  commitSha: z.string(),
1289
- parentCommitSha: z.string(),
1290
- clientCommitSha: z.string(),
1319
+ /** `null` for a root commit. See `ValCommit`. */
1320
+ parentCommitSha: z.string().nullable(),
1321
+ /** `null` when the publisher did not say where it was. See `ValCommit`. */
1322
+ clientCommitSha: z.string().nullable(),
1291
1323
  branch: z.string(),
1292
1324
  createdBranch: z.string().nullable(),
1293
1325
  creator: z.string().nullable(),
@@ -1385,7 +1417,7 @@ var ValConfig = z.object({
1385
1417
  gitCommit: z.string().optional(),
1386
1418
  gitBranch: z.string().optional()
1387
1419
  });
1388
- var ValidationFixZ = z.union([z.literal("image:add-metadata"), z.literal("image:check-metadata"), z.literal("image:check-remote"), z.literal("image:upload-remote"), z.literal("image:download-remote"), z.literal("images:check-remote"), z.literal("images:upload-remote"), z.literal("file:add-metadata"), z.literal("file:check-metadata"), z.literal("file:check-remote"), z.literal("file:upload-remote"), z.literal("file:download-remote"), z.literal("files:check-remote"), z.literal("files:upload-remote"), z.literal("keyof:check-keys"), z.literal("router:check-route"), z.literal("locale:check-locale"), z.literal("record:fill-keys"), z.literal("images:check-unique-folder"), z.literal("files:check-unique-folder"), z.literal("images:check-all-files"), z.literal("files:check-all-files"), z.literal("jsonValues:extract-entry")]);
1420
+ var ValidationFixZ = z.union([z.literal("image:add-metadata"), z.literal("image:check-metadata"), z.literal("image:check-remote"), z.literal("image:upload-remote"), z.literal("image:download-remote"), z.literal("images:check-remote"), z.literal("images:upload-remote"), z.literal("file:add-metadata"), z.literal("file:check-metadata"), z.literal("file:check-remote"), z.literal("file:upload-remote"), z.literal("file:download-remote"), z.literal("files:check-remote"), z.literal("files:upload-remote"), z.literal("keyof:check-keys"), z.literal("router:check-route"), z.literal("locale:check-locale"), z.literal("record:fill-keys"), z.literal("images:check-unique-folder"), z.literal("files:check-unique-folder"), z.literal("images:check-all-files"), z.literal("files:check-all-files"), z.literal("jsonValues:extract-entry"), z.literal("view:check-module")]);
1389
1421
  var ValidationError = z.object({
1390
1422
  message: z.string(),
1391
1423
  value: z.unknown().optional(),
@@ -1408,6 +1440,27 @@ var GenericError = z.object({
1408
1440
  message: z.string()
1409
1441
  });
1410
1442
 
1443
+ /**
1444
+ * Why a publish cannot happen, in a form the Studio can show.
1445
+ *
1446
+ * Carried on `/stat` so the action is disabled with the reason beside it, and
1447
+ * on `/save`'s 409 so the same answer is given to a client that asked anyway --
1448
+ * a stat can be a poll out of date, and nothing may reach the commit path on a
1449
+ * project this deployment cannot publish.
1450
+ *
1451
+ * `no-base` is the only code so far: there is nowhere for this publish's
1452
+ * commit to be based. Note which way round that is. A project whose content
1453
+ * service is the store of record always HAS a base -- the service's own chain,
1454
+ * which mints its own shas -- so this is not about a missing git repository.
1455
+ * It is about a deployment that cannot do what its project requires: one built
1456
+ * before the project attached a repository, now asked to mirror commits into
1457
+ * one it knows no commit for.
1458
+ */
1459
+ var PublishRefusal = z.object({
1460
+ code: z.literal("no-base"),
1461
+ message: z.string()
1462
+ });
1463
+
1411
1464
  /**
1412
1465
  * A patch group: the set of patches one user has chosen to publish.
1413
1466
  *
@@ -1803,7 +1856,8 @@ var Api = {
1803
1856
  config: ValConfig,
1804
1857
  profileId: z.string().nullable(),
1805
1858
  mode: z.union([z.literal("http"), z.literal("fs")]),
1806
- jsonEntriesSha: z.string().optional()
1859
+ jsonEntriesSha: z.string().optional(),
1860
+ publishRefusal: PublishRefusal.optional()
1807
1861
  }), z.object({
1808
1862
  type: z.literal("use-websocket"),
1809
1863
  url: z.string(),
@@ -1811,7 +1865,16 @@ var Api = {
1811
1865
  baseSha: z.string(),
1812
1866
  schemaSha: z.string(),
1813
1867
  sourcesSha: z.string(),
1814
- commitSha: z.string(),
1868
+ /**
1869
+ * The commit this deployment was built from.
1870
+ *
1871
+ * Optional: a project whose content service is the store of
1872
+ * record has no repository and no commit baked into its build.
1873
+ * The Studio has always parsed this as optional -- see
1874
+ * `useStatus` -- and shows a branch and a commit only when there
1875
+ * is one.
1876
+ */
1877
+ commitSha: z.string().optional(),
1815
1878
  patches: z.array(PatchId),
1816
1879
  /**
1817
1880
  * Of `patches`, the ones that have already SHIPPED.
@@ -1855,7 +1918,8 @@ var Api = {
1855
1918
  deployments: z.array(ValDeployment).optional(),
1856
1919
  config: ValConfig,
1857
1920
  profileId: z.string().nullable(),
1858
- mode: z.union([z.literal("http"), z.literal("fs")])
1921
+ mode: z.union([z.literal("http"), z.literal("fs")]),
1922
+ publishRefusal: PublishRefusal.optional()
1859
1923
  })])
1860
1924
  })])
1861
1925
  }
@@ -2376,7 +2440,19 @@ var Api = {
2376
2440
  json: GenericError
2377
2441
  }), z.object({
2378
2442
  status: z.literal(409),
2379
- json: z.union([/** A group that has already shipped. See the 403 above. */
2443
+ json: z.union([
2444
+ /*
2445
+ * This deployment cannot publish this project at all.
2446
+ *
2447
+ * First in the union so it is read before the bare
2448
+ * `{ message }` above it would swallow it. `/stat` carries the
2449
+ * same refusal, so a Studio that is up to date never sends a save
2450
+ * that lands here -- this is for the one that is a poll behind.
2451
+ */
2452
+ z.object({
2453
+ message: z.string(),
2454
+ publishRefusal: PublishRefusal
2455
+ }), /** A group that has already shipped. See the 403 above. */
2380
2456
  z.object({
2381
2457
  message: z.string()
2382
2458
  }), z.object({
@@ -4690,6 +4766,13 @@ function emptyOf(schema, context) {
4690
4766
  }, (_schema$options$forma = (_schema$options = schema.options) === null || _schema$options === void 0 ? void 0 : _schema$options.format) !== null && _schema$options$forma !== void 0 ? _schema$options$forma : DEFAULT_COLOR_FORMAT);
4691
4767
  } else if (schema.type === "code") {
4692
4768
  return ""; // An empty editor: no language has a sensible starting snippet
4769
+ } else if (schema.type === "view") {
4770
+ // The pointer IS the empty value: a view has exactly one valid source, and
4771
+ // the schema knows it. A new page with a view field gets the same pointer
4772
+ // every other page's has.
4773
+ return {
4774
+ view: schema.moduleFilePath
4775
+ };
4693
4776
  }
4694
4777
  var _exhaustiveCheck = schema;
4695
4778
  throw Error("Unexpected schema type: " + JSON.stringify(_exhaustiveCheck));
@@ -5337,6 +5420,8 @@ function isSkippableFixCode(fix) {
5337
5420
  case "files:check-unique-folder":
5338
5421
  case "images:check-all-files":
5339
5422
  case "files:check-all-files":
5423
+ case "view:check-module":
5424
+ // schema is code: nothing for an editor to do
5340
5425
  return true;
5341
5426
  case "keyof:check-keys":
5342
5427
  case "router:check-route":
@@ -5818,6 +5903,12 @@ function traverseSchemaSource(source, schema, path, callback) {
5818
5903
  }
5819
5904
  return;
5820
5905
  }
5906
+ if (schema.type === "view") {
5907
+ // The source here is a pointer — a module file path, not content. Indexing
5908
+ // it would make every view a hit for its target's filename, and the target
5909
+ // is already indexed under its own path.
5910
+ return;
5911
+ }
5821
5912
 
5822
5913
  // Exhaustive check
5823
5914
  var exhaustiveCheck = schema;
@@ -6617,4 +6708,4 @@ function resolvePairGround(ground, ramp) {
6617
6708
  return typeof ground === "number" ? ramp[ground] : ground;
6618
6709
  }
6619
6710
 
6620
- 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, PatchGroup, PatchId, PatchJSON, RAMP_STEPS, RemirrorBr, RemirrorBulletList, RemirrorHeading, RemirrorImage, RemirrorJSON, RemirrorLinkMark, RemirrorListItem, RemirrorOrderedList, RemirrorParagraph, RemirrorText, RemirrorTextMark, RestoreVerdict, RichTextOptions, SCHEMA_SOURCE_FIXES, SerializedArraySchema, SerializedBooleanSchema, SerializedCodeSchema, SerializedColorSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedFileSchema, SerializedImageSchema, SerializedKeyOfSchema, SerializedLiteralSchema, SerializedLocaleSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedRecordSchema, SerializedRichTextSchema, SerializedRouteSchema, SerializedSchema, SerializedSettingsSchema, SerializedStringSchema, SharedValConfig, VAL_ENABLE_COOKIE_NAME, VAL_GREEN_RAMP, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, ValCommit, ValDeployment, accentRamp, buildDuplicatePatch, buildEmptyAtPathPatch, buildFileRefValue, buildImageGalleryPatch, buildRemoveImageGalleryEntryPatch, buildSearchIndex, checkCompatibility, chooseEncoded, concatModulePath, contrastRatio, createRegExpFromPattern, createSearchIndex, createValClient, declaredLocales, describeContainerAtPath, emptyOf, explainIncompatible, filterBlockingValidationErrors, filterRoutesByPatterns, findSimilar, fitWithin, flattenRichText, getErrorMessageFromUnknownJson, getFilenameFromRef, getInlineImgInfo, getKeyOfRecordAt, getRefParts, getRoutesOf, getRoutesWithModulePaths, getSourceAt, indexModule, isMimeTypeAccepted, isRemoteSchema, isSchemaSourceFixError, isSkippedSource, keyOfRecordPath, levenshtein, localeAt, newestCommitSha, partitionValidationErrors, performSearch, relativeLuminance, remirrorToRichTextSource, removeModule, resolveEncodeSettings, resolvePairGround, resolveSchemaSourceFixForError, resolveSchemaSourceFixes, resolveSerializedSchemaAtPath, richTextToRemirror, safeParsePatch, sourcePathOfChild, themeCustomProperties, toolNames, traverseSchemaSource, urlOf, validateRoutePatterns, withExtension };
6711
+ 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, PatchGroup, PatchId, PatchJSON, RAMP_STEPS, RemirrorBr, RemirrorBulletList, RemirrorHeading, RemirrorImage, RemirrorJSON, RemirrorLinkMark, RemirrorListItem, RemirrorOrderedList, RemirrorParagraph, RemirrorText, RemirrorTextMark, RestoreVerdict, RichTextOptions, SCHEMA_SOURCE_FIXES, SerializedArraySchema, SerializedBooleanSchema, SerializedCodeSchema, SerializedColorSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedFileSchema, SerializedImageSchema, SerializedKeyOfSchema, SerializedLiteralSchema, SerializedLocaleSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedRecordSchema, SerializedRichTextSchema, SerializedRouteSchema, SerializedSchema, SerializedSettingsSchema, SerializedStringSchema, SerializedValViewSchema, SharedValConfig, VAL_ENABLE_COOKIE_NAME, VAL_GREEN_RAMP, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, ValCommit, ValDeployment, accentRamp, buildDuplicatePatch, buildEmptyAtPathPatch, buildFileRefValue, buildImageGalleryPatch, buildRemoveImageGalleryEntryPatch, buildSearchIndex, checkCompatibility, chooseEncoded, concatModulePath, contrastRatio, createRegExpFromPattern, createSearchIndex, createValClient, declaredLocales, describeContainerAtPath, emptyOf, explainIncompatible, filterBlockingValidationErrors, filterRoutesByPatterns, findSimilar, fitWithin, flattenRichText, getErrorMessageFromUnknownJson, getFilenameFromRef, getInlineImgInfo, getKeyOfRecordAt, getRefParts, getRoutesOf, getRoutesWithModulePaths, getSourceAt, indexModule, isMimeTypeAccepted, isRemoteSchema, isSchemaSourceFixError, isSkippedSource, keyOfRecordPath, levenshtein, localeAt, newestCommitSha, partitionValidationErrors, performSearch, relativeLuminance, remirrorToRichTextSource, removeModule, resolveEncodeSettings, resolvePairGround, resolveSchemaSourceFixForError, resolveSchemaSourceFixes, resolveSerializedSchemaAtPath, richTextToRemirror, safeParsePatch, sourcePathOfChild, themeCustomProperties, toolNames, traverseSchemaSource, urlOf, validateRoutePatterns, withExtension };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valbuild/shared",
3
- "version": "0.130.0",
3
+ "version": "0.134.0",
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.130.0"
40
+ "@valbuild/core": "0.134.0"
41
41
  },
42
42
  "files": [
43
43
  "CHANGELOG.md",