@valbuild/shared 0.140.2 → 0.142.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.
@@ -1165,13 +1165,16 @@ var SerializedRecordSchema = zod.z.lazy(function () {
1165
1165
  type: zod.z.literal("record"),
1166
1166
  item: SerializedSchema,
1167
1167
  opt: zod.z["boolean"](),
1168
- // Optional gallery marker for files/images
1169
- mediaType: zod.z.union([zod.z.literal("files"), zod.z.literal("images")]).optional(),
1168
+ // Optional gallery marker for files/images/videos
1169
+ mediaType: zod.z.union([zod.z.literal("files"), zod.z.literal("images"), zod.z.literal("videos")]).optional(),
1170
1170
  // Optional legacy gallery metadata
1171
1171
  accept: zod.z.string().optional(),
1172
1172
  dir: zod.z.string().optional(),
1173
1173
  remote: zod.z["boolean"]().optional(),
1174
1174
  encode: ImageEncodeOption.optional(),
1175
+ // A videoset's: see `VideoStreamOption` below for why it is spelled
1176
+ // out rather than passed through.
1177
+ stream: VideoStreamOption.optional(),
1175
1178
  alt: SerializedSchema.optional(),
1176
1179
  moduleMetadata: zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.any())).optional()
1177
1180
  })).passthrough());
@@ -1205,6 +1208,29 @@ var SerializedFileSchema = zod.z.object(getSitemapTree._objectSpread2(getSitemap
1205
1208
  remote: zod.z["boolean"]().optional(),
1206
1209
  referencedModule: zod.z.string().optional()
1207
1210
  }));
1211
+
1212
+ // `stream` is the one option that changes what an upload BECOMES, so it is
1213
+ // declared field by field: these z.objects strip unknown keys, and a stream
1214
+ // dropped in transit is a Studio that uploads a 2 GB mp4 where an HLS stream
1215
+ // was asked for.
1216
+ var VideoStreamOption = zod.z.union([zod.z.literal(false), zod.z.object({
1217
+ type: zod.z.literal("hls"),
1218
+ renditions: zod.z.array(zod.z.number()).optional(),
1219
+ segmentDuration: zod.z.number().optional()
1220
+ })]);
1221
+ var VideoOptions = zod.z.object({
1222
+ dir: zod.z.string().optional(),
1223
+ accept: zod.z.string().optional(),
1224
+ stream: VideoStreamOption.optional()
1225
+ });
1226
+ var SerializedVideoSchema = zod.z.object(getSitemapTree._objectSpread2(getSitemapTree._objectSpread2({}, commonSchemaFields), {}, {
1227
+ type: zod.z.literal("video"),
1228
+ options: VideoOptions.optional(),
1229
+ opt: zod.z["boolean"](),
1230
+ remote: zod.z["boolean"]().optional(),
1231
+ // The `s.videoset()` a set-backed field picks from.
1232
+ referencedModule: zod.z.string().optional()
1233
+ }));
1208
1234
  var DateOptions = zod.z.object({
1209
1235
  from: zod.z.string().optional(),
1210
1236
  to: zod.z.string().optional()
@@ -1295,7 +1321,7 @@ var SerializedValViewSchema = zod.z.object({
1295
1321
  hidden: zod.z["boolean"]().optional(),
1296
1322
  description: zod.z.string().optional()
1297
1323
  });
1298
- 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]);
1324
+ 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, SerializedVideoSchema, SerializedValViewSchema]);
1299
1325
 
1300
1326
  var ValCommit = zod.z.object({
1301
1327
  commitSha: zod.z.string(),
@@ -1476,12 +1502,12 @@ var ValConfig = zod.z.object({
1476
1502
  project: zod.z.string().optional(),
1477
1503
  root: zod.z.string().optional(),
1478
1504
  files: zod.z.object({
1479
- directory: zod.z.string() // TODO: validate that it is prefixed by /public/
1505
+ remote: zod.z["boolean"]().optional()
1480
1506
  }).optional(),
1481
1507
  gitCommit: zod.z.string().optional(),
1482
1508
  gitBranch: zod.z.string().optional()
1483
1509
  });
1484
- 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")]);
1510
+ 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("video:add-metadata"), zod.z.literal("video:upload-remote"), zod.z.literal("video:download-remote"), zod.z.literal("videos:add-metadata"), zod.z.literal("videos:check-remote"), zod.z.literal("videos:upload-remote"), 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("videos:check-unique-folder"), zod.z.literal("videos:check-all-files"), zod.z.literal("jsonValues:extract-entry"), zod.z.literal("view:check-module")]);
1485
1511
  var ValidationError = zod.z.object({
1486
1512
  message: zod.z.string(),
1487
1513
  value: zod.z.unknown().optional(),
@@ -1576,6 +1602,14 @@ var PublishRefusal = zod.z.object({
1576
1602
  message: zod.z.string()
1577
1603
  });
1578
1604
 
1605
+ /** See `proposal` on `/stat`. */
1606
+ var StatProposal = zod.z.object({
1607
+ /** Twenty hex characters, the hash of what it was made from. */
1608
+ name: zod.z.string(),
1609
+ /** `val/p/<name>`. */
1610
+ branch: zod.z.string()
1611
+ });
1612
+
1579
1613
  /**
1580
1614
  * A patch group: the set of patches one user has chosen to publish.
1581
1615
  *
@@ -2006,7 +2040,13 @@ var Api = {
2006
2040
  * connected ones by commit.
2007
2041
  */
2008
2042
  publishJobs: zod.z["boolean"]().optional(),
2009
- publishRefusal: PublishRefusal.optional()
2043
+ publishRefusal: PublishRefusal.optional(),
2044
+ /**
2045
+ * The proposal this server runs at the address of, or absent
2046
+ * on the site. What the Studio's switcher says it is in, and
2047
+ * where its Save goes (valbuild/home `docs/proposals.md`).
2048
+ */
2049
+ proposal: StatProposal.optional()
2010
2050
  }), zod.z.object({
2011
2051
  type: zod.z.literal("use-websocket"),
2012
2052
  url: zod.z.string(),
@@ -2124,7 +2164,13 @@ var Api = {
2124
2164
  * connected ones by commit.
2125
2165
  */
2126
2166
  publishJobs: zod.z["boolean"]().optional(),
2127
- publishRefusal: PublishRefusal.optional()
2167
+ publishRefusal: PublishRefusal.optional(),
2168
+ /**
2169
+ * The proposal this server runs at the address of, or absent
2170
+ * on the site. What the Studio's switcher says it is in, and
2171
+ * where its Save goes (valbuild/home `docs/proposals.md`).
2172
+ */
2173
+ proposal: StatProposal.optional()
2128
2174
  })])
2129
2175
  })])
2130
2176
  }
@@ -2210,6 +2256,60 @@ var Api = {
2210
2256
  })
2211
2257
  }
2212
2258
  },
2259
+ /**
2260
+ * The content service's proposals API, reached through this deployment:
2261
+ * list, open, read, rename, close, reopen and retry a setup
2262
+ * (valbuild/home `docs/proposals.md`, Flow B).
2263
+ *
2264
+ * The same arrangement as `/publish-api`, for the same reasons: the browser
2265
+ * holds a session for this origin and no credential content accepts, so
2266
+ * this server checks the session, sends the project's key with the person's
2267
+ * profile id beside it -- a proposal is opened, renamed and closed by
2268
+ * somebody -- and carries content's status and body back unread. The sub-path
2269
+ * is content's, after `/proposals`; `ValOpsHttp.proposalsApi` holds the
2270
+ * allow list. A save is not here: it is `/save`, which a proposal's server
2271
+ * sends to the proposal's own route.
2272
+ */
2273
+ "/proposals-api": {
2274
+ GET: {
2275
+ req: {
2276
+ path: zod.z.string().optional(),
2277
+ cookies: {
2278
+ val_session: zod.z.string().optional()
2279
+ }
2280
+ },
2281
+ res: zod.z.object({
2282
+ status: zod.z.number(),
2283
+ json: zod.z.unknown()
2284
+ })
2285
+ },
2286
+ POST: {
2287
+ req: {
2288
+ path: zod.z.string().optional(),
2289
+ body: zod.z.unknown().optional(),
2290
+ cookies: {
2291
+ val_session: zod.z.string().optional()
2292
+ }
2293
+ },
2294
+ res: zod.z.object({
2295
+ status: zod.z.number(),
2296
+ json: zod.z.unknown()
2297
+ })
2298
+ },
2299
+ PATCH: {
2300
+ req: {
2301
+ path: zod.z.string().optional(),
2302
+ body: zod.z.unknown().optional(),
2303
+ cookies: {
2304
+ val_session: zod.z.string().optional()
2305
+ }
2306
+ },
2307
+ res: zod.z.object({
2308
+ status: zod.z.number(),
2309
+ json: zod.z.unknown()
2310
+ })
2311
+ }
2312
+ },
2213
2313
  "/upload/patches": {
2214
2314
  POST: {
2215
2315
  req: {
@@ -2739,6 +2839,32 @@ var Api = {
2739
2839
  })])
2740
2840
  }
2741
2841
  },
2842
+ /**
2843
+ * In a proposal: the SITE's Source for every module the proposal has saved,
2844
+ * as the build it is based on has it. What Compare with the site diffs the
2845
+ * proposal against -- saved and unsaved alike -- because the Studio's own
2846
+ * base Source there is the proposal's last save. 404 anywhere that is not a
2847
+ * proposal's address. valbuild/home `docs/proposals.md`.
2848
+ */
2849
+ "/proposal-site-sources": {
2850
+ GET: {
2851
+ req: {
2852
+ cookies: {
2853
+ val_session: zod.z.string().optional()
2854
+ }
2855
+ },
2856
+ res: zod.z.union([unauthorizedResponse, zod.z.object({
2857
+ status: zod.z.literal(404),
2858
+ json: GenericError
2859
+ }), zod.z.object({
2860
+ status: zod.z.literal(200),
2861
+ json: zod.z.object({
2862
+ /** By module file path. A module absent here is the same in both. */
2863
+ modules: zod.z.record(zod.z.string(), zod.z.unknown())
2864
+ })
2865
+ })])
2866
+ }
2867
+ },
2742
2868
  "/profiles": {
2743
2869
  GET: {
2744
2870
  req: {
@@ -3194,11 +3320,23 @@ var Api = {
3194
3320
  return arg[0];
3195
3321
  }).optional(),
3196
3322
  remote: onlyOneStringQueryParam.optional()
3323
+ },
3324
+ // A `<video>` seeks with byte ranges, Safari will not play one from a
3325
+ // server that ignores them, and HLS segments that are byte ranges of
3326
+ // one file are fetched no other way.
3327
+ headers: {
3328
+ range: zod.z.string().optional()
3197
3329
  }
3198
3330
  },
3199
3331
  res: zod.z.union([unauthorizedResponse, notFoundResponse, zod.z.object({
3200
3332
  status: zod.z.literal(200),
3201
3333
  body: zod.z["instanceof"](ReadableStream)
3334
+ }), zod.z.object({
3335
+ status: zod.z.literal(206),
3336
+ body: zod.z["instanceof"](ReadableStream)
3337
+ }), zod.z.object({
3338
+ status: zod.z.literal(416),
3339
+ json: GenericError
3202
3340
  })])
3203
3341
  }
3204
3342
  },
@@ -5322,7 +5460,7 @@ function emptyOf(schema, context) {
5322
5460
  // language nobody chose, which is the thing this whole feature exists to
5323
5461
  // make visible.
5324
5462
  return (_context$selectedLoca = context === null || context === void 0 ? void 0 : context.selectedLocale) !== null && _context$selectedLoca !== void 0 ? _context$selectedLoca : "";
5325
- } else if (schema.type === "file" || schema.type === "image") {
5463
+ } else if (schema.type === "file" || schema.type === "image" || schema.type === "video") {
5326
5464
  return null; // returning null is the only thing we can do, however, it means that the patches cannot be applied yet since that might fail
5327
5465
  } else if (schema.type === "literal") {
5328
5466
  return schema.value;
@@ -5532,6 +5670,14 @@ function checkGallerySchema(moduleSchema) {
5532
5670
  if (moduleSchema.type === "record" && moduleSchema.mediaType === "images") {
5533
5671
  return null;
5534
5672
  }
5673
+ if (moduleSchema.type === "record" && moduleSchema.mediaType === "videos") {
5674
+ // Said outright rather than as "not an images gallery": a set of videos
5675
+ // looks like a gallery from here, and the tool can do nothing with one.
5676
+ return {
5677
+ kind: "error",
5678
+ message: "Module is a video set (s.videoset()), not an images gallery. Videos cannot be added or removed by this tool: upload them in Val Studio."
5679
+ };
5680
+ }
5535
5681
  if (moduleSchema.type === "image") {
5536
5682
  return {
5537
5683
  kind: "wrong-tool",
@@ -5626,17 +5772,32 @@ var GALLERY_REDIRECT = {
5626
5772
  reason: "Destination is a media gallery (s.imageset() / s.fileset()). Gallery entries are keyed by file path and carry a file on disk, so they cannot be created with a plain patch. Use add_session_image_to_gallery."
5627
5773
  };
5628
5774
 
5629
- /** An `s.imageset()` / `s.fileset()` record: a gallery, not an ordinary record. */
5775
+ /**
5776
+ * A video set's entries are keyed by a file too, and a stream's by a
5777
+ * directory of them — and there is no tool to send them to: a video is
5778
+ * uploaded (and, for a stream, transcoded) in the Studio.
5779
+ */
5780
+ var VIDEOSET_REFUSAL = {
5781
+ kind: "error",
5782
+ message: "Destination is a video set (s.videoset()). Its entries are keyed by file path and carry video files, so they cannot be created with a plain patch, and no tool here uploads a video: add it in Val Studio."
5783
+ };
5784
+
5785
+ /** An `s.imageset()` / `s.fileset()` / `s.videoset()` record: a gallery, not an ordinary record. */
5630
5786
  function isGallery(schema) {
5631
5787
  return schema.type === "record" && schema.mediaType !== undefined;
5632
5788
  }
5789
+
5790
+ /** Where to send someone whose destination is (in) the gallery `schema`. */
5791
+ function galleryRedirect(schema) {
5792
+ return schema.type === "record" && schema.mediaType === "videos" ? VIDEOSET_REFUSAL : GALLERY_REDIRECT;
5793
+ }
5633
5794
  function decideOp(moduleSchema, destinationPath) {
5634
5795
  // The DESTINATION itself, checked before its parent: `["gallery"]` resolves
5635
5796
  // its parent to the enclosing object and would otherwise look like an
5636
5797
  // ordinary `replace` that overwrites a whole gallery.
5637
5798
  var destination = resolveSerializedSchemaAtPath(moduleSchema, destinationPath);
5638
5799
  if (destination.kind === "gallery-traversed") {
5639
- return GALLERY_REDIRECT;
5800
+ return galleryRedirect(destination.schema);
5640
5801
  }
5641
5802
  if (destination.kind === "richtext") {
5642
5803
  return {
@@ -5647,7 +5808,7 @@ function decideOp(moduleSchema, destinationPath) {
5647
5808
  }
5648
5809
  if (destination.kind === "leaf") {
5649
5810
  if (isGallery(destination.schema)) {
5650
- return GALLERY_REDIRECT;
5811
+ return galleryRedirect(destination.schema);
5651
5812
  }
5652
5813
  // A richtext value the path lands exactly ON resolves as a leaf, not as
5653
5814
  // `kind: "richtext"` (which only fires when the walk continues INTO it).
@@ -5684,7 +5845,7 @@ function decideOp(moduleSchema, destinationPath) {
5684
5845
  // destination is a gallery entry; `isGallery` catches the case where the
5685
5846
  // parent IS the gallery and the destination is a new entry key in it.
5686
5847
  if (parent.kind === "gallery-traversed" || isGallery(parent.schema)) {
5687
- return GALLERY_REDIRECT;
5848
+ return galleryRedirect(parent.schema);
5688
5849
  }
5689
5850
  var schema = parent.schema;
5690
5851
  if (schema.type === "array" || schema.type === "record") {
@@ -6005,6 +6166,14 @@ function isSkippableFixCode(fix) {
6005
6166
  case "file:check-remote":
6006
6167
  case "files:check-remote":
6007
6168
  case "files:upload-remote":
6169
+ case "video:add-metadata": // the Studio writes it on upload; --fix for the rest
6170
+ case "video:upload-remote":
6171
+ case "video:download-remote":
6172
+ case "videos:add-metadata": // as `video:add-metadata`, for a set's entry
6173
+ case "videos:check-remote":
6174
+ case "videos:upload-remote":
6175
+ case "videos:check-unique-folder":
6176
+ case "videos:check-all-files":
6008
6177
  case "images:check-unique-folder":
6009
6178
  case "files:check-unique-folder":
6010
6179
  case "images:check-all-files":
@@ -6329,8 +6498,8 @@ function traverseSchemaSource(source, schema, path, callback) {
6329
6498
  return;
6330
6499
  }
6331
6500
 
6332
- // Handle file/image
6333
- if (schema.type === "file" || schema.type === "image") {
6501
+ // Handle file/image/video
6502
+ if (schema.type === "file" || schema.type === "image" || schema.type === "video") {
6334
6503
  if (source && getSitemapTree._typeof(source) === "object" && "path" in source && typeof source.path === "string") {
6335
6504
  callback({
6336
6505
  source: source,
@@ -6677,8 +6846,8 @@ function indexModule(searchIndex, moduleFilePath, source, schema) {
6677
6846
  // Use first 50 chars as label
6678
6847
  label = searchText.substring(0, 50) || "richtext";
6679
6848
  }
6680
- // Handle file/image
6681
- else if (schema.type === "file" || schema.type === "image") {
6849
+ // Handle file/image/video
6850
+ else if (schema.type === "file" || schema.type === "image" || schema.type === "video") {
6682
6851
  if (source !== null && getSitemapTree._typeof(source) === "object" && "path" in source && typeof source.path === "string") {
6683
6852
  // The label is the bare filename - the folder is shown separately in
6684
6853
  // the UI - but both are searchable.
@@ -7852,6 +8021,7 @@ exports.SerializedSchema = SerializedSchema;
7852
8021
  exports.SerializedSettingsSchema = SerializedSettingsSchema;
7853
8022
  exports.SerializedStringSchema = SerializedStringSchema;
7854
8023
  exports.SerializedValViewSchema = SerializedValViewSchema;
8024
+ exports.SerializedVideoSchema = SerializedVideoSchema;
7855
8025
  exports.SharedValConfig = SharedValConfig;
7856
8026
  exports.VAL_ENABLE_COOKIE_NAME = VAL_ENABLE_COOKIE_NAME;
7857
8027
  exports.VAL_GREEN_RAMP = VAL_GREEN_RAMP;
@@ -7860,6 +8030,8 @@ exports.VAL_STATE_COOKIE = VAL_STATE_COOKIE;
7860
8030
  exports.VAL_STUDIO_HEADER = VAL_STUDIO_HEADER;
7861
8031
  exports.ValCommit = ValCommit;
7862
8032
  exports.ValDeployment = ValDeployment;
8033
+ exports.VideoOptions = VideoOptions;
8034
+ exports.VideoStreamOption = VideoStreamOption;
7863
8035
  exports.accentRamp = accentRamp;
7864
8036
  exports.buildDuplicatePatch = buildDuplicatePatch;
7865
8037
  exports.buildEmptyAtPathPatch = buildEmptyAtPathPatch;