@valbuild/core 0.126.0 → 0.128.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.
Files changed (32) hide show
  1. package/CHANGELOG.md +296 -0
  2. package/dist/declarations/src/index.d.ts +5 -1
  3. package/dist/declarations/src/initSchema.d.ts +31 -15
  4. package/dist/declarations/src/locale.d.ts +55 -0
  5. package/dist/declarations/src/schema/array.d.ts +4 -0
  6. package/dist/declarations/src/schema/declaredKeys.d.ts +37 -0
  7. package/dist/declarations/src/schema/discriminatedUnion.d.ts +4 -0
  8. package/dist/declarations/src/schema/discriminatedUnionBranch.d.ts +20 -0
  9. package/dist/declarations/src/schema/enum.d.ts +9 -0
  10. package/dist/declarations/src/schema/file.d.ts +3 -3
  11. package/dist/declarations/src/schema/{files.d.ts → fileset.d.ts} +10 -10
  12. package/dist/declarations/src/schema/hasRemoteFileSchema.d.ts +3 -3
  13. package/dist/declarations/src/schema/image.d.ts +9 -5
  14. package/dist/declarations/src/schema/{images.d.ts → imageset.d.ts} +54 -21
  15. package/dist/declarations/src/schema/index.d.ts +116 -3
  16. package/dist/declarations/src/schema/literal.d.ts +2 -0
  17. package/dist/declarations/src/schema/locale.d.ts +132 -0
  18. package/dist/declarations/src/schema/object.d.ts +7 -0
  19. package/dist/declarations/src/schema/record.d.ts +57 -7
  20. package/dist/declarations/src/schema/settings.d.ts +54 -1
  21. package/dist/declarations/src/schema/validation/ValidationFix.d.ts +1 -1
  22. package/dist/declarations/src/source/settings.d.ts +51 -0
  23. package/dist/{index-6db78f3c.cjs.prod.js → index-053ccde2.cjs.prod.js} +1114 -91
  24. package/dist/{index-b41b638f.cjs.dev.js → index-c3ae637d.cjs.dev.js} +1114 -91
  25. package/dist/{index-cd25c2dc.esm.js → index-db41de3c.esm.js} +1109 -92
  26. package/dist/valbuild-core.cjs.dev.js +7 -1
  27. package/dist/valbuild-core.cjs.prod.js +7 -1
  28. package/dist/valbuild-core.esm.js +1 -1
  29. package/package.json +1 -1
  30. package/patch/dist/valbuild-core-patch.cjs.dev.js +1 -1
  31. package/patch/dist/valbuild-core-patch.cjs.prod.js +1 -1
  32. package/patch/dist/valbuild-core-patch.esm.js +2 -2
@@ -161,19 +161,217 @@ function _inherits(t, e) {
161
161
  // import { SerializedI18nSchema } from "./future/i18n";
162
162
  // import { SerializedOneOfSchema } from "./future/oneOf";
163
163
 
164
+ /**
165
+ * A locale scope's path, as something to read in a message.
166
+ *
167
+ * The walk names the item of an array or record `*`, which says nothing to
168
+ * whoever has to fix this. `[]` is the convention people already read as "each
169
+ * of these", and a path that is nothing BUT items has no field to name at all.
170
+ */
171
+ function describeScopePath(path) {
172
+ if (path.every(function (segment) {
173
+ return segment === "*";
174
+ })) {
175
+ return "its entries";
176
+ }
177
+ var rendered = "";
178
+ var _iterator = _createForOfIteratorHelper(path),
179
+ _step;
180
+ try {
181
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
182
+ var segment = _step.value;
183
+ if (segment === "*") {
184
+ rendered += "[]";
185
+ } else {
186
+ rendered += rendered === "" ? segment : ".".concat(segment);
187
+ }
188
+ }
189
+ } catch (err) {
190
+ _iterator.e(err);
191
+ } finally {
192
+ _iterator.f();
193
+ }
194
+ return "'".concat(rendered, "'");
195
+ }
164
196
  var Schema = /*#__PURE__*/function () {
165
197
  function Schema() {
166
198
  _classCallCheck(this, Schema);
199
+ /**
200
+ * The answer, computed once per schema.
201
+ *
202
+ * Memoised because the question is asked from `executeValidate`, which runs
203
+ * once per SOURCE instance: an array of five hundred blocks asks the item
204
+ * schema five hundred times, and each answer walks the schema below it
205
+ * looking for a nested scope. The answer cannot differ between two instances
206
+ * of the same schema — nothing here reads the source — so the walk is done
207
+ * once and the result handed back after that.
208
+ *
209
+ * The error is still reported at every instance's path. Val's validation
210
+ * errors are keyed by source path and that is where the Studio draws them, so
211
+ * a schema error on a row is a schema error on every row; reporting it on one
212
+ * arbitrary row would put it somewhere nobody was looking.
213
+ */
214
+ _defineProperty(this, "localeScopeErrorsMemo", void 0);
167
215
  }
168
216
  return _createClass(Schema, [{
217
+ key: "isLocaleField",
218
+ value:
219
+ /**
220
+ * Whether this node is a locale — the field that MARKS a scope, `s.locale()`.
221
+ *
222
+ * Only `LocaleSchema` overrides this. A base implementation rather than an
223
+ * abstract one on purpose: every other schema class answers no, and a
224
+ * question every class had to answer would be twenty edits for one yes.
225
+ *
226
+ * Not the same question as {@link opensLocaleScope}: a locale field marks the
227
+ * scope, the object AROUND it is the scope. See `localeScope.ts`.
228
+ */
229
+ function isLocaleField() {
230
+ return false;
231
+ }
232
+
233
+ /**
234
+ * Whether this node OPENS a locale scope, and what opens it.
235
+ *
236
+ * An object with a `s.locale()` field opens one; so does a record keyed by
237
+ * `s.locale()`. Everything below such a node is in that one language, which
238
+ * is why a scope may not contain another — see `localeScope.ts` for the rule
239
+ * and the reason it is validated rather than typed.
240
+ */
241
+ }, {
242
+ key: "opensLocaleScope",
243
+ value: function opensLocaleScope() {
244
+ return null;
245
+ }
246
+
247
+ /**
248
+ * The child schemas a locale scope reaches, by the path segment that reaches
249
+ * them.
250
+ *
251
+ * A structural walk that deliberately does NOT go through `executeSerialize`:
252
+ * serializing a subtree at every node to ask a question about its shape is
253
+ * quadratic, and this is asked during validation. `*` stands for the item of
254
+ * an array or record, which has no name of its own.
255
+ */
256
+ }, {
257
+ key: "localeScopeChildren",
258
+ value: function localeScopeChildren() {
259
+ return [];
260
+ }
261
+
262
+ /**
263
+ * Every locale scope opened strictly BELOW this node, by path.
264
+ *
265
+ * Stops descending at each one it finds, so a scope three deep is reported
266
+ * once, by the scope immediately enclosing it, rather than by every ancestor.
267
+ */
268
+ }, {
269
+ key: "localeScopesBelow",
270
+ value: function localeScopesBelow() {
271
+ var prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
272
+ var found = [];
273
+ var _iterator2 = _createForOfIteratorHelper(this.localeScopeChildren()),
274
+ _step2;
275
+ try {
276
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
277
+ var _step2$value = _step2.value,
278
+ key = _step2$value.key,
279
+ schema = _step2$value.schema;
280
+ var _path = [].concat(_toConsumableArray(prefix), [key]);
281
+ var opened = schema.opensLocaleScope();
282
+ if (opened !== null) {
283
+ found.push({
284
+ path: _path,
285
+ kind: opened
286
+ });
287
+ continue;
288
+ }
289
+ found.push.apply(found, _toConsumableArray(schema.localeScopesBelow(_path)));
290
+ }
291
+ } catch (err) {
292
+ _iterator2.e(err);
293
+ } finally {
294
+ _iterator2.f();
295
+ }
296
+ return found;
297
+ }
298
+
299
+ /**
300
+ * The scope rule, as errors at this node — or `false` if it is not broken.
301
+ *
302
+ * Two things are wrong and both are wrong in the SCHEMA rather than in the
303
+ * content, so both are `schemaError`s: an object with two locale fields (the
304
+ * subtree below it would be in two languages at once), and a locale scope
305
+ * inside another (the inner one would silently override the outer for part
306
+ * of a subtree that is supposed to be one language throughout).
307
+ *
308
+ * Validated rather than typed on purpose. Expressing "no scope below this
309
+ * one" as a constraint means threading it through every schema class's type
310
+ * parameter, and the errors that fall out of a recursive constraint like
311
+ * that name the whole tree — an unrelated typo in a `.val.ts` would print
312
+ * pages. See the design notes on the locales PR.
313
+ */
314
+ }, {
315
+ key: "localeScopeErrors",
316
+ value: function localeScopeErrors() {
317
+ if (this.localeScopeErrorsMemo === undefined) {
318
+ this.localeScopeErrorsMemo = this.computeLocaleScopeErrors();
319
+ }
320
+ return this.localeScopeErrorsMemo;
321
+ }
322
+ }, {
323
+ key: "computeLocaleScopeErrors",
324
+ value: function computeLocaleScopeErrors() {
325
+ var errors = [];
326
+ var localeFields = this.localeFieldNames();
327
+ if (localeFields.length > 1) {
328
+ errors.push({
329
+ message: "An object can be in one language, so it can have one locale field. Found ".concat(localeFields.map(function (each) {
330
+ return "'".concat(each, "'");
331
+ }).join(", "), "."),
332
+ schemaError: true
333
+ });
334
+ }
335
+ var opened = this.opensLocaleScope();
336
+ if (opened !== null) {
337
+ var _iterator3 = _createForOfIteratorHelper(this.localeScopesBelow()),
338
+ _step3;
339
+ try {
340
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
341
+ var nested = _step3.value;
342
+ errors.push({
343
+ message: "Everything here is already in one language, so ".concat(describeScopePath(nested.path), " cannot set another. Move the ").concat(nested.kind === "key" ? "locale-keyed record" : "locale field", " out of this ").concat(opened === "key" ? "locale-keyed record" : "object", ", or take the outer one away."),
344
+ schemaError: true
345
+ });
346
+ }
347
+ } catch (err) {
348
+ _iterator3.e(err);
349
+ } finally {
350
+ _iterator3.f();
351
+ }
352
+ }
353
+ return errors;
354
+ }
355
+
356
+ /**
357
+ * This node's own `s.locale()` fields, where it is an object that has any.
358
+ *
359
+ * Empty everywhere else, so `localeScopeErrors` can live on the base class.
360
+ */
361
+ }, {
362
+ key: "localeFieldNames",
363
+ value: function localeFieldNames() {
364
+ return [];
365
+ }
366
+ }, {
169
367
  key: "executeCustomValidateFunctions",
170
368
  value: function executeCustomValidateFunctions(src, customValidateFunctions, ctx) {
171
369
  var errors = [];
172
- var _iterator = _createForOfIteratorHelper(customValidateFunctions),
173
- _step;
370
+ var _iterator4 = _createForOfIteratorHelper(customValidateFunctions),
371
+ _step4;
174
372
  try {
175
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
176
- var customValidateFunction = _step.value;
373
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
374
+ var customValidateFunction = _step4.value;
177
375
  try {
178
376
  var result = customValidateFunction(src, ctx);
179
377
  if (result) {
@@ -191,9 +389,9 @@ var Schema = /*#__PURE__*/function () {
191
389
  }
192
390
  }
193
391
  } catch (err) {
194
- _iterator.e(err);
392
+ _iterator4.e(err);
195
393
  } finally {
196
- _iterator.f();
394
+ _iterator4.f();
197
395
  }
198
396
  return errors;
199
397
  }
@@ -292,11 +490,11 @@ var Schema = /*#__PURE__*/function () {
292
490
  return incoming;
293
491
  }
294
492
  for (var pathS in incoming) {
295
- var _path = pathS;
296
- if (current[_path]) {
297
- current[_path] = current[_path].concat(incoming[_path]);
493
+ var _path2 = pathS;
494
+ if (current[_path2]) {
495
+ current[_path2] = current[_path2].concat(incoming[_path2]);
298
496
  } else {
299
- current[_path] = incoming[_path];
497
+ current[_path2] = incoming[_path2];
300
498
  }
301
499
  }
302
500
  return current;
@@ -331,6 +529,10 @@ var GetSource = Symbol["for"]("@valbuild/core/GetSource");
331
529
  var ValError = Symbol["for"]("@valbuild/core/ValError");
332
530
  var GenericSelector = /*#__PURE__*/_createClass(function GenericSelector(valOrExpr, path, schema, error) {
333
531
  _classCallCheck(this, GenericSelector);
532
+ _defineProperty(this, Path, void 0);
533
+ _defineProperty(this, GetSource, void 0);
534
+ _defineProperty(this, ValError, void 0);
535
+ _defineProperty(this, GetSchema, void 0);
334
536
  this[Path] = path;
335
537
  this[GetSource] = valOrExpr;
336
538
  this[ValError] = error;
@@ -933,6 +1135,18 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
933
1135
  } finally {
934
1136
  _iterator.f();
935
1137
  }
1138
+ var _iterator2 = _createForOfIteratorHelper(this.localeScopeErrors()),
1139
+ _step2;
1140
+ try {
1141
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
1142
+ var scopeError = _step2.value;
1143
+ error = this.appendValidationError(error, path, scopeError.message, src, scopeError.schemaError);
1144
+ }
1145
+ } catch (err) {
1146
+ _iterator2.e(err);
1147
+ } finally {
1148
+ _iterator2.f();
1149
+ }
936
1150
  for (var _i = 0, _Object$entries = Object.entries(this.items); _i < _Object$entries.length; _i++) {
937
1151
  var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
938
1152
  _key = _Object$entries$_i[0],
@@ -1016,7 +1230,7 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
1016
1230
  key: "nullable",
1017
1231
  value: function nullable() {
1018
1232
  // Explicit type args: `previewInput` would otherwise pin inference to `Src`.
1019
- return new ObjectSchema(this.items, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
1233
+ return new ObjectSchema(this.items, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
1020
1234
  }
1021
1235
  }, {
1022
1236
  key: "readonly",
@@ -1030,6 +1244,35 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
1030
1244
  var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
1031
1245
  return new ObjectSchema(this.items, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
1032
1246
  }
1247
+
1248
+ /** The names of this object's `s.locale()` fields, in declaration order. */
1249
+ }, {
1250
+ key: "localeFieldNames",
1251
+ value: function localeFieldNames() {
1252
+ var _this2 = this;
1253
+ return Object.keys(this.items).filter(function (key) {
1254
+ return _this2.items[key]["isLocaleField"]();
1255
+ });
1256
+ }
1257
+ }, {
1258
+ key: "opensLocaleScope",
1259
+ value: function opensLocaleScope() {
1260
+ // More than one is itself the error, reported by `localeScopeErrors`. It
1261
+ // still opens a scope: reporting "two locale fields" AND "a scope inside a
1262
+ // scope" for the same object would be two errors about one mistake.
1263
+ return this.localeFieldNames().length > 0 ? "field" : null;
1264
+ }
1265
+ }, {
1266
+ key: "localeScopeChildren",
1267
+ value: function localeScopeChildren() {
1268
+ var _this3 = this;
1269
+ return Object.keys(this.items).map(function (key) {
1270
+ return {
1271
+ key: key,
1272
+ schema: _this3.items[key]
1273
+ };
1274
+ });
1275
+ }
1033
1276
  }, {
1034
1277
  key: "executeCustomValidateAt",
1035
1278
  value: function executeCustomValidateAt(path, src) {
@@ -1294,7 +1537,7 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
1294
1537
  key: "nullable",
1295
1538
  value: function nullable() {
1296
1539
  // Explicit type args: `previewInput` would otherwise pin inference to `Src`.
1297
- return new ArraySchema(this.item, true, [], this.isReadonly, this.isHidden, this.description, this.previewInput, this.renderInput);
1540
+ return new ArraySchema(this.item, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.previewInput, this.renderInput);
1298
1541
  }
1299
1542
  }, {
1300
1543
  key: "readonly",
@@ -1308,6 +1551,14 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
1308
1551
  var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
1309
1552
  return new ArraySchema(this.item, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.previewInput, this.renderInput);
1310
1553
  }
1554
+ }, {
1555
+ key: "localeScopeChildren",
1556
+ value: function localeScopeChildren() {
1557
+ return [{
1558
+ key: "*",
1559
+ schema: this.item
1560
+ }];
1561
+ }
1311
1562
  }, {
1312
1563
  key: "executeCustomValidateAt",
1313
1564
  value: function executeCustomValidateAt(path, src) {
@@ -1481,6 +1732,8 @@ var array = function array(schema) {
1481
1732
  };
1482
1733
 
1483
1734
  var LiteralSchema = /*#__PURE__*/function (_Schema) {
1735
+ /** Type-only marker: as a record key, this declares the key set. See `LocaleSchema`. */
1736
+
1484
1737
  function LiteralSchema(value) {
1485
1738
  var _this;
1486
1739
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
@@ -1612,7 +1865,7 @@ var LiteralSchema = /*#__PURE__*/function (_Schema) {
1612
1865
  }, {
1613
1866
  key: "nullable",
1614
1867
  value: function nullable() {
1615
- return new LiteralSchema(this.value, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
1868
+ return new LiteralSchema(this.value, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
1616
1869
  }
1617
1870
  }, {
1618
1871
  key: "readonly",
@@ -2033,7 +2286,7 @@ var DiscriminatedUnionSchema = /*#__PURE__*/function (_Schema) {
2033
2286
  key: "nullable",
2034
2287
  value: function nullable() {
2035
2288
  // Explicit type args: `previewInput` would otherwise pin inference to `Src`.
2036
- return new DiscriminatedUnionSchema(this.key, this.items, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
2289
+ return new DiscriminatedUnionSchema(this.key, this.items, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
2037
2290
  }
2038
2291
  }, {
2039
2292
  key: "readonly",
@@ -2047,6 +2300,20 @@ var DiscriminatedUnionSchema = /*#__PURE__*/function (_Schema) {
2047
2300
  var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
2048
2301
  return new DiscriminatedUnionSchema(this.key, this.items, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
2049
2302
  }
2303
+ }, {
2304
+ key: "localeScopeChildren",
2305
+ value: function localeScopeChildren() {
2306
+ // Every variant is walked under the SAME path: whichever one the value
2307
+ // takes, that is where it sits. `s.enum()` has no children at all — its
2308
+ // values are strings, not schemas — which is why only this half of the old
2309
+ // `s.union` has this.
2310
+ return this.items.map(function (item) {
2311
+ return {
2312
+ key: "*",
2313
+ schema: item
2314
+ };
2315
+ });
2316
+ }
2050
2317
  }, {
2051
2318
  key: "executeCustomValidateAt",
2052
2319
  value: function executeCustomValidateAt(path, src) {
@@ -3259,7 +3526,7 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
3259
3526
  *
3260
3527
  * @example
3261
3528
  * const schema = s
3262
- * .image({ accept: "image/webp", directory: "/public/val/images" })
3529
+ * .image({ accept: "image/webp", dir: "/public/val/images" })
3263
3530
  * .remote();
3264
3531
  * export default c.define("/example.val.ts", schema, {
3265
3532
  * path: "https://remote.val.build/file/p/my-project/b/01/v/1.0.0/h/8f2a1c/f/3b9d70/p/public/val/images/example.webp",
@@ -3438,6 +3705,10 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
3438
3705
  /**
3439
3706
  * The entries of the gallery this field points at, or null when it is a
3440
3707
  * standalone field.
3708
+ *
3709
+ * `AltSource` rather than a specific alt type: a field never reads an entry's
3710
+ * alt — it carries its own — so it only needs the entry keys and the
3711
+ * dimensions, and a gallery of any alt shape can back it.
3441
3712
  */
3442
3713
  }, {
3443
3714
  key: "galleryEntries",
@@ -4457,7 +4728,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
4457
4728
  }, {
4458
4729
  key: "nullable",
4459
4730
  value: function nullable() {
4460
- return new RichTextSchema(this.options, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
4731
+ return new RichTextSchema(this.options, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
4461
4732
  }
4462
4733
  }, {
4463
4734
  key: "readonly",
@@ -4974,6 +5245,68 @@ function hasInlineExternalEntries(source) {
4974
5245
  return _typeof(source) === "object" && source !== null && !Array.isArray(source) && !isExternal(source) && Object.keys(source).length > 0;
4975
5246
  }
4976
5247
 
5248
+ /**
5249
+ * The keys a record is REQUIRED to hold, where its key schema says what they are.
5250
+ *
5251
+ * Most records have an open key set — `s.record(s.string(), item)` holds
5252
+ * whatever anyone adds — and this returns `null` for those. A record keyed by
5253
+ * something that enumerates its values is different in kind: the keys are part
5254
+ * of the schema, so a missing one is a hole in the content rather than content
5255
+ * nobody has written yet.
5256
+ *
5257
+ * Two key schemas enumerate. A union of literals does it locally, so its keys
5258
+ * are here. `s.locale()` does it in the settings module, which is another file
5259
+ * and so cannot be read from a serialized schema — that case says only which
5260
+ * kind it is, and is resolved against `locales.available` by
5261
+ * `resolveSchemaSourceFixes`, the same crossing `keyOf` and `route` make.
5262
+ */
5263
+
5264
+ /**
5265
+ * What `key` requires a record to hold, or `null` where it requires nothing.
5266
+ *
5267
+ * Works from the SERIALIZED schema so that the Studio, the validation worker
5268
+ * and the server all answer this the same way — none of them has the schema
5269
+ * instance, and `SchemaStore` deliberately holds serialized schemas only.
5270
+ */
5271
+ function declaredKeySetOf(key) {
5272
+ if (key === undefined) {
5273
+ return null;
5274
+ }
5275
+ if (key.type === "literal") {
5276
+ return {
5277
+ kind: "literals",
5278
+ keys: [key.value]
5279
+ };
5280
+ }
5281
+ if (key.type === "enum") {
5282
+ // An enum names every value it may take, so those values ARE the key set.
5283
+ // `discriminated-union` is deliberately absent: it discriminates objects
5284
+ // and cannot be a record key at all.
5285
+ return {
5286
+ kind: "literals",
5287
+ keys: _toConsumableArray(key.values)
5288
+ };
5289
+ }
5290
+ if (key.type === "locale") {
5291
+ return {
5292
+ kind: "locale"
5293
+ };
5294
+ }
5295
+ return null;
5296
+ }
5297
+
5298
+ /**
5299
+ * The declared keys a record is missing, in the order the schema declares them.
5300
+ *
5301
+ * Declaration order rather than the source's: this is read as "what is left to
5302
+ * write", and the answer should not reshuffle itself as entries are added.
5303
+ */
5304
+ function missingDeclaredKeys(declared, present) {
5305
+ return declared.filter(function (key) {
5306
+ return !present.includes(key);
5307
+ });
5308
+ }
5309
+
4977
5310
  /**
4978
5311
  * The source type of a `.jsonValues()` record: every entry value is EITHER a
4979
5312
  * lazily loaded {@link JsonSource} whose resolved content is the (loosened, see
@@ -5005,6 +5338,16 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5005
5338
  var externalLabel = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : null;
5006
5339
  _classCallCheck(this, RecordSchema);
5007
5340
  _this = _callSuper(this, RecordSchema);
5341
+ /**
5342
+ * The key set this record's schema declares, computed once.
5343
+ *
5344
+ * `declaredKeySetOf` reads a SERIALIZED schema, and serializing the key
5345
+ * schema walks it — twice per validate, and once per record instance, for an
5346
+ * answer that is a property of the schema and cannot move between them. A
5347
+ * schema is built once and validated against many times, so the walk happens
5348
+ * on the first question and not on any after it.
5349
+ */
5350
+ _defineProperty(_this, "declaredKeys", void 0);
5008
5351
  _this.item = item;
5009
5352
  _this.opt = opt;
5010
5353
  _this.customValidateFunctions = customValidateFunctions;
@@ -5120,9 +5463,9 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5120
5463
  if (this.mediaOptions) {
5121
5464
  var checkFix = this.mediaOptions.type === "images" ? "images:check-unique-folder" : "files:check-unique-folder";
5122
5465
  var uniqueCheckError = {
5123
- message: "Gallery directory '".concat(this.mediaOptions.directory, "' must be unique across all galleries"),
5466
+ message: "Gallery directory '".concat(this.mediaOptions.dir, "' must be unique across all galleries"),
5124
5467
  value: {
5125
- directory: this.mediaOptions.directory,
5468
+ dir: this.mediaOptions.dir,
5126
5469
  type: this.mediaOptions.type
5127
5470
  },
5128
5471
  fixes: [checkFix]
@@ -5138,9 +5481,9 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5138
5481
  }
5139
5482
  var allFilesCheckFix = this.mediaOptions.type === "images" ? "images:check-all-files" : "files:check-all-files";
5140
5483
  var allFilesCheckError = {
5141
- message: "Directory '".concat(this.mediaOptions.directory, "' may have files not tracked by this gallery"),
5484
+ message: "Directory '".concat(this.mediaOptions.dir, "' may have files not tracked by this gallery"),
5142
5485
  value: {
5143
- directory: this.mediaOptions.directory,
5486
+ dir: this.mediaOptions.dir,
5144
5487
  type: this.mediaOptions.type
5145
5488
  },
5146
5489
  fixes: [allFilesCheckFix]
@@ -5151,6 +5494,11 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5151
5494
  error = _objectSpread2(_objectSpread2({}, error), {}, _defineProperty({}, path, [allFilesCheckError]));
5152
5495
  }
5153
5496
  }
5497
+ // A record whose keys are declared by its schema holds every one of them,
5498
+ // and an entry nobody has written yet is `null` rather than absent — so
5499
+ // `null` is a value here, not a value of the wrong type, and the item
5500
+ // schema is not asked about it.
5501
+ var hasDeclaredKeys = this.declaredKeySet() !== null;
5154
5502
  Object.entries(src).forEach(function (_ref5) {
5155
5503
  var _ref6 = _slicedToArray(_ref5, 2),
5156
5504
  key = _ref6[0],
@@ -5190,7 +5538,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5190
5538
  _this2.markKeyErrorsAtPath(entryErr, subPath);
5191
5539
  }
5192
5540
  error = _this2.mergeValidationErrors(error, entryErr);
5193
- } else if (_this2.isJsonValues && isJson(elem)) ; else {
5541
+ } else if (hasDeclaredKeys && elem === null) ; else if (_this2.isJsonValues && isJson(elem)) ; else {
5194
5542
  // Falls through for a jsonValues record whose entry content is inlined
5195
5543
  // (loaded in the UI, or hand-authored): same as a plain record — validate
5196
5544
  // the value against the item schema.
@@ -5198,8 +5546,79 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5198
5546
  error = _this2.mergeValidationErrors(error, subError);
5199
5547
  }
5200
5548
  });
5549
+ var declaredKeys = this.getDeclaredKeysValidation(path, src);
5550
+ error = this.mergeValidationErrors(error, declaredKeys);
5551
+ var _iterator2 = _createForOfIteratorHelper(this.localeScopeErrors()),
5552
+ _step2;
5553
+ try {
5554
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
5555
+ var scopeError = _step2.value;
5556
+ error = this.appendValidationError(error, path, scopeError.message, src, scopeError.schemaError);
5557
+ }
5558
+ } catch (err) {
5559
+ _iterator2.e(err);
5560
+ } finally {
5561
+ _iterator2.f();
5562
+ }
5201
5563
  return error;
5202
5564
  }
5565
+
5566
+ /**
5567
+ * The check that a record with a DECLARED key set holds every one of them.
5568
+ *
5569
+ * `s.record(s.locale(), item)` has one entry per language and
5570
+ * `s.record(s.union(s.literal("a"), s.literal("b")), item)` has both — the
5571
+ * keys are part of the schema either way, so a missing one is a hole in the
5572
+ * content rather than content nobody has written yet. TypeScript already
5573
+ * demanded both keys of the second; this is the validator catching up, which
5574
+ * is why the two now behave the same.
5575
+ *
5576
+ * Deferred to `resolveSchemaSourceFixes` even for the literal case, where the
5577
+ * keys are known right here: a locale record's keys are in another file, and
5578
+ * one code path for both is one message, one fix and one thing to be wrong.
5579
+ */
5580
+ }, {
5581
+ key: "getDeclaredKeysValidation",
5582
+ value: function getDeclaredKeysValidation(path, src) {
5583
+ if (this.keySchema === null) {
5584
+ return false;
5585
+ }
5586
+ var declared = this.declaredKeySet();
5587
+ if (declared === null) {
5588
+ return false;
5589
+ }
5590
+ return _defineProperty({}, path, [{
5591
+ fixes: ["record:fill-keys"],
5592
+ message: "Did not validate record keys. This error (record:fill-keys) should typically be processed by Val internally. Seeing this error most likely means you have a Val version mismatch.",
5593
+ value: {
5594
+ present: Object.keys(src),
5595
+ declared: declared.kind === "literals" ? declared.keys : null
5596
+ }
5597
+ }]);
5598
+ }
5599
+ }, {
5600
+ key: "declaredKeySet",
5601
+ value: function declaredKeySet() {
5602
+ if (this.declaredKeys === undefined) {
5603
+ this.declaredKeys = this.keySchema === null ? null : declaredKeySetOf(this.keySchema["executeSerialize"]());
5604
+ }
5605
+ return this.declaredKeys;
5606
+ }
5607
+ }, {
5608
+ key: "opensLocaleScope",
5609
+ value: function opensLocaleScope() {
5610
+ return this.keySchema !== null && this.keySchema["isLocaleField"]() ? "key" : null;
5611
+ }
5612
+ }, {
5613
+ key: "localeScopeChildren",
5614
+ value: function localeScopeChildren() {
5615
+ // The KEY schema is not a child here. A locale key is what opens this
5616
+ // record's scope; it is not something inside the scope.
5617
+ return [{
5618
+ key: "*",
5619
+ schema: this.item
5620
+ }];
5621
+ }
5203
5622
  }, {
5204
5623
  key: "isRemoteUrl",
5205
5624
  value: function isRemoteUrl(url) {
@@ -5225,13 +5644,13 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5225
5644
  return false;
5226
5645
  }
5227
5646
  var _this$mediaOptions = this.mediaOptions,
5228
- directory = _this$mediaOptions.directory,
5647
+ dir = _this$mediaOptions.dir,
5229
5648
  isRemote = _this$mediaOptions.remote,
5230
5649
  type = _this$mediaOptions.type;
5231
5650
  var mediaLabel = type === "images" ? "images" : "files";
5232
5651
  var checkRemoteFix = type === "images" ? "images:check-remote" : "files:check-remote";
5233
5652
  var isRemoteUrl = this.isRemoteUrl(key);
5234
- var isLocalPath = key === directory || key.startsWith(directory + "/");
5653
+ var isLocalPath = key === dir || key.startsWith(dir + "/");
5235
5654
  if (isRemote) {
5236
5655
  // When remote is enabled, accept either remote URLs or local paths
5237
5656
  if (isRemoteUrl) {
@@ -5246,9 +5665,9 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5246
5665
  }
5247
5666
  // Check that the file path in the remote URL matches our directory constraint
5248
5667
  var remotePath = "/" + remoteResult.filePath;
5249
- if (remotePath !== directory && !remotePath.startsWith(directory + "/")) {
5668
+ if (remotePath !== dir && !remotePath.startsWith(dir + "/")) {
5250
5669
  return _defineProperty({}, path, [{
5251
- message: "Remote file path '".concat(remotePath, "' is not in expected directory '").concat(directory, "'. Use Val tooling to upload ").concat(mediaLabel, " to the correct directory."),
5670
+ message: "Remote file path '".concat(remotePath, "' is not in expected directory '").concat(dir, "'. Use Val tooling to upload ").concat(mediaLabel, " to the correct directory."),
5252
5671
  value: key,
5253
5672
  fixes: [checkRemoteFix]
5254
5673
  }]);
@@ -5257,7 +5676,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5257
5676
  }
5258
5677
  if (!isLocalPath) {
5259
5678
  return _defineProperty({}, path, [{
5260
- message: "Expected a remote URL (https://...) or a local path starting with ".concat(directory, "/. Got: ").concat(key),
5679
+ message: "Expected a remote URL (https://...) or a local path starting with ".concat(dir, "/. Got: ").concat(key),
5261
5680
  value: key
5262
5681
  }]);
5263
5682
  }
@@ -5279,7 +5698,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5279
5698
  }
5280
5699
  if (!isLocalPath) {
5281
5700
  return _defineProperty({}, path, [{
5282
- message: "File path must be within the ".concat(directory, "/ directory. Got: ").concat(key),
5701
+ message: "File path must be within the ".concat(dir, "/ directory. Got: ").concat(key),
5283
5702
  value: key
5284
5703
  }]);
5285
5704
  }
@@ -5475,7 +5894,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5475
5894
  * Allow the files in this gallery to be stored on Val's remote content host
5476
5895
  * instead of in your repository.
5477
5896
  *
5478
- * For `s.images()` and `s.files()`, which are records of media. Remote is off
5897
+ * For `s.imageset()` and `s.fileset()`, which are records of media. Remote is off
5479
5898
  * until this is called.
5480
5899
  *
5481
5900
  * Each entry is then keyed by its URL on the content host rather than by a
@@ -5484,7 +5903,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5484
5903
  * upload it and rewrite the key.
5485
5904
  *
5486
5905
  * @example
5487
- * const schema = s.images({ directory: "/public/val/images" }).remote();
5906
+ * const schema = s.imageset({ dir: "/public/val/images" }).remote();
5488
5907
  * export default c.define("/content/images.val.ts", schema, {
5489
5908
  * "https://remote.val.build/file/p/my-project/b/01/v/1.0.0/h/8f2a1c/f/3b9d70/p/public/val/images/hero.webp":
5490
5909
  * {
@@ -5510,7 +5929,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5510
5929
  * which lets the runtime, the Studio and validation work one entry at a time
5511
5930
  * so a record/router can scale to many thousands of entries.
5512
5931
  *
5513
- * Not supported on image/file galleries (`s.images()` / `s.files()`).
5932
+ * Not supported on image/file galleries (`s.imageset()` / `s.fileset()`).
5514
5933
  *
5515
5934
  * Only supported on a module's ROOT record/router — a `.jsonValues()` record
5516
5935
  * nested inside an object/array/record is rejected at startup with a module
@@ -5535,7 +5954,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5535
5954
  key: "jsonValues",
5536
5955
  value: function jsonValues() {
5537
5956
  if (this.mediaOptions) {
5538
- throw new Error(".jsonValues() cannot be used with image/file galleries (s.images()/s.files())");
5957
+ throw new Error(".jsonValues() cannot be used with image/file galleries (s.imageset()/s.fileset())");
5539
5958
  }
5540
5959
  if (this.customValidateFunctions.length > 0) {
5541
5960
  // `.jsonValues()` changes the source shape to JsonSource entries, so a
@@ -5564,7 +5983,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5564
5983
  * bucket — instead of in the module.
5565
5984
  *
5566
5985
  * Available on every record-derived schema, which is `s.record()`,
5567
- * `s.router()`, `s.images()` and `s.files()` alike: a router is a
5986
+ * `s.router()`, `s.imageset()` and `s.fileset()` alike: a router is a
5568
5987
  * `RecordSchema` with a `ValRouter`, a gallery one with media options, so all
5569
5988
  * four get external storage from this one method.
5570
5989
  *
@@ -5719,7 +6138,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5719
6138
  if (this.mediaOptions) {
5720
6139
  result.mediaType = this.mediaOptions.type;
5721
6140
  result.accept = this.mediaOptions.accept;
5722
- result.directory = this.mediaOptions.directory;
6141
+ result.dir = this.mediaOptions.dir;
5723
6142
  result.remote = this.mediaOptions.remote;
5724
6143
  if (this.mediaOptions.encode !== undefined) {
5725
6144
  result.encode = this.mediaOptions.encode;
@@ -5894,6 +6313,23 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5894
6313
  }]);
5895
6314
  }(Schema);
5896
6315
 
6316
+ /**
6317
+ * The source of a record, given what its key schema says about its keys.
6318
+ *
6319
+ * A key schema that ENUMERATES its keys (a union of literals, or `s.locale()`)
6320
+ * makes every one of them an entry of the record, and an entry nobody has
6321
+ * written yet is `null` rather than absent — so the value type widens by
6322
+ * `null`. That is the whole of option F at the type level: a half-translated
6323
+ * record is a record with nulls in it, which is data you can count, filter and
6324
+ * see in a diff, rather than keys that are simply not there.
6325
+ *
6326
+ * For a union of literals TypeScript already required every key, since
6327
+ * `SelectorOfSchema<K>` is the literal union itself. `s.locale()` is a flavoured
6328
+ * string, so it requires nothing here and the requirement is the validator's —
6329
+ * deliberately: which languages exist is in the settings module, where the
6330
+ * project can change it without a deploy.
6331
+ */
6332
+
5897
6333
  // Overload: with key schema
5898
6334
 
5899
6335
  // Overload: without key schema
@@ -5932,6 +6368,31 @@ function record(keyOrSchema, schema) {
5932
6368
  * written without removing the key.
5933
6369
  */
5934
6370
 
6371
+ /**
6372
+ * The languages this project publishes.
6373
+ *
6374
+ * Content rather than configuration, and deliberately: which languages a site
6375
+ * has is a decision the people who write it make, and under a build-time
6376
+ * constant it took a developer and a deploy. It is the same move `assistant`
6377
+ * makes with `enabled`.
6378
+ *
6379
+ * Val ships no list of its own. A project with no `locales` section has not
6380
+ * said it is translated, and nothing about locales appears anywhere — no picker
6381
+ * in the Studio, no checks, nothing.
6382
+ *
6383
+ * **This list is a decision with a blast radius.** Every locale in content is
6384
+ * checked against it, so removing one invalidates the content that uses it, and
6385
+ * adding one leaves every locale-keyed record short of a language until it is
6386
+ * filled in. That is the intended behaviour — a language that is declared and
6387
+ * missing everywhere is worth being told about — but it is why the Studio warns
6388
+ * before saving a removal rather than treating this as an ordinary field.
6389
+ *
6390
+ * There is no default language, deliberately. Every locale-specific field asks
6391
+ * which language it is in, and a default is exactly the answer that lets that
6392
+ * question go unanswered — content ends up filed under a language nobody chose,
6393
+ * which is the state translation is meant to make visible.
6394
+ */
6395
+
5935
6396
  /**
5936
6397
  * The assistant: whether editors have one, and what it is told about the
5937
6398
  * project on every message.
@@ -5992,6 +6453,263 @@ settings) {
5992
6453
  return "unconfigured";
5993
6454
  }
5994
6455
 
6456
+ /**
6457
+ * One of the languages the project publishes.
6458
+ *
6459
+ * The set is NOT here. It is declared in the settings module — `locales.available`
6460
+ * — so that adding a language is something the people who write the content can
6461
+ * do, and so that one list drives validation, the Studio's picker and the
6462
+ * translation notes. This schema knows only that the value is one of them, which
6463
+ * is checked cross-module through the `locale:check-locale` fix, exactly as
6464
+ * `keyOf` and `route` check theirs.
6465
+ *
6466
+ * Never stega encoded (see `stegaEncode.ts`): a locale goes into `<html lang>`,
6467
+ * into `hreflang` and into `Intl` constructors, none of which survive invisible
6468
+ * characters.
6469
+ */
6470
+ var LocaleSchema = /*#__PURE__*/function (_Schema) {
6471
+ /**
6472
+ * Type-only marker: as a record key, this schema DECLARES the key set.
6473
+ *
6474
+ * `declare` so it exists in the type and nowhere at runtime — reading it off
6475
+ * an instance gives `undefined`, and nothing should. It is how `record()`
6476
+ * knows to type entries as `Item | null`: a language nobody has translated
6477
+ * into is a null entry, not an absent key. See `DeclaredKeySet` and
6478
+ * `RecordSrcOf`.
6479
+ */
6480
+
6481
+ function LocaleSchema() {
6482
+ var _this;
6483
+ var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
6484
+ var customValidateFunctions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
6485
+ var isReadonly = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
6486
+ var isHidden = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
6487
+ var description = arguments.length > 4 ? arguments[4] : undefined;
6488
+ var renderInput = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;
6489
+ var previewInput = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
6490
+ _classCallCheck(this, LocaleSchema);
6491
+ _this = _callSuper(this, LocaleSchema);
6492
+ _this.opt = opt;
6493
+ _this.customValidateFunctions = customValidateFunctions;
6494
+ _this.isReadonly = isReadonly;
6495
+ _this.isHidden = isHidden;
6496
+ _this.description = description;
6497
+ _this.renderInput = renderInput;
6498
+ _this.previewInput = previewInput;
6499
+ return _this;
6500
+ }
6501
+
6502
+ /**
6503
+ * A note to whoever edits this field, shown under it in the Studio.
6504
+ *
6505
+ * Pass `null` to clear a description set earlier.
6506
+ *
6507
+ * @example
6508
+ * const schema = s.object({
6509
+ * locale: s.locale().describe("The language everything below is written in"),
6510
+ * title: s.string(),
6511
+ * });
6512
+ * export default c.define("/example.val.ts", schema, {
6513
+ * locale: "nb-NO",
6514
+ * title: "Vinterjakke",
6515
+ * });
6516
+ */
6517
+ _inherits(LocaleSchema, _Schema);
6518
+ return _createClass(LocaleSchema, [{
6519
+ key: "describe",
6520
+ value: function describe(description) {
6521
+ return new LocaleSchema(this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
6522
+ }
6523
+
6524
+ /**
6525
+ * A check of your own, on top of "is this one of the project's languages".
6526
+ *
6527
+ * Return a message when the value is WRONG and `false` when it is fine — the
6528
+ * two answers are a complaint and no complaint, so write the check as a
6529
+ * ternary rather than as `ok || "message"`, which returns `true` and `true`
6530
+ * is neither.
6531
+ *
6532
+ * @example
6533
+ * const schema = s.object({
6534
+ * locale: s.locale().validate((val) =>
6535
+ * val === "en-US" ? "This section is not translated into English yet" : false,
6536
+ * ),
6537
+ * title: s.string(),
6538
+ * });
6539
+ * export default c.define("/example.val.ts", schema, {
6540
+ * locale: "nb-NO",
6541
+ * title: "Vinterjakke",
6542
+ * });
6543
+ */
6544
+ }, {
6545
+ key: "validate",
6546
+ value: function validate(validationFunction) {
6547
+ return new LocaleSchema(this.opt, this.customValidateFunctions.concat(validationFunction), this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
6548
+ }
6549
+ }, {
6550
+ key: "executeValidate",
6551
+ value: function executeValidate(path, src) {
6552
+ var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
6553
+ path: path
6554
+ });
6555
+ if (this.opt && (src === null || src === undefined)) {
6556
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
6557
+ }
6558
+ if (typeof src !== "string") {
6559
+ return _defineProperty({}, path, [{
6560
+ message: "Expected 'string', got '".concat(_typeof(src), "'"),
6561
+ value: src
6562
+ }]);
6563
+ }
6564
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
6565
+ // Which languages exist is in another module, so this cannot be
6566
+ // answered here — the same shape `keyOf` and `route` use, resolved by
6567
+ // `resolveSchemaSourceFixes` against the settings module.
6568
+ fixes: ["locale:check-locale"],
6569
+ message: "Did not validate locale. This error (locale:check-locale) should typically be processed by Val internally. Seeing this error most likely means you have a Val version mismatch.",
6570
+ value: {
6571
+ locale: src,
6572
+ sourcePath: path
6573
+ }
6574
+ }]));
6575
+ }
6576
+ }, {
6577
+ key: "executeAssert",
6578
+ value: function executeAssert(path, src) {
6579
+ if (this.opt && src === null) {
6580
+ return {
6581
+ success: true,
6582
+ data: src
6583
+ };
6584
+ }
6585
+ if (typeof src === "string") {
6586
+ return {
6587
+ success: true,
6588
+ data: src
6589
+ };
6590
+ }
6591
+ return {
6592
+ success: false,
6593
+ errors: _defineProperty({}, path, [{
6594
+ message: "Expected 'string', got '".concat(_typeof(src), "'"),
6595
+ typeError: true
6596
+ }])
6597
+ };
6598
+ }
6599
+ }, {
6600
+ key: "nullable",
6601
+ value: function nullable() {
6602
+ // Asserted whole, exactly as `RouteSchema.nullable` does: the source type
6603
+ // widens by `null` while the caller's validators and preview stay typed
6604
+ // against the value, and `executeValidate` returns before either sees one.
6605
+ return new LocaleSchema(true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
6606
+ }
6607
+ }, {
6608
+ key: "readonly",
6609
+ value: function readonly() {
6610
+ return new LocaleSchema(this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
6611
+ }
6612
+ }, {
6613
+ key: "hidden",
6614
+ value: function hidden() {
6615
+ return new LocaleSchema(this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
6616
+ }
6617
+ }, {
6618
+ key: "isLocaleField",
6619
+ value: function isLocaleField() {
6620
+ return true;
6621
+ }
6622
+ }, {
6623
+ key: "executeCustomValidateAt",
6624
+ value: function executeCustomValidateAt(path, src) {
6625
+ return this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
6626
+ path: path
6627
+ });
6628
+ }
6629
+
6630
+ /**
6631
+ * How this field is laid out where it is the item of an array or a record.
6632
+ * Static configuration, not a callback — see `render.ts`.
6633
+ *
6634
+ * @example
6635
+ * const schema = s.array(s.locale().render({ as: "inline" }));
6636
+ * export default c.define("/example.val.ts", schema, ["nb-NO", "en-US"]);
6637
+ */
6638
+ }, {
6639
+ key: "render",
6640
+ value: function render(input) {
6641
+ return new LocaleSchema(this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, input, this.previewInput);
6642
+ }
6643
+
6644
+ /**
6645
+ * How this VALUE is shown where a preview of it is needed. Never how the field
6646
+ * itself is edited (that is `render`). See `preview.ts`.
6647
+ *
6648
+ * @example
6649
+ * const schema = s.array(
6650
+ * s.locale().preview(({ val }) => ({ title: val })),
6651
+ * );
6652
+ * export default c.define("/example.val.ts", schema, ["nb-NO", "en-US"]);
6653
+ */
6654
+ }, {
6655
+ key: "preview",
6656
+ value: function preview(select) {
6657
+ return new LocaleSchema(this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, select);
6658
+ }
6659
+ }, {
6660
+ key: "executePreviewItem",
6661
+ value: function executePreviewItem(src) {
6662
+ if (this.previewInput === null) {
6663
+ return null;
6664
+ }
6665
+ return this.previewInput({
6666
+ val: src
6667
+ });
6668
+ }
6669
+ }, {
6670
+ key: "declaresItemPreview",
6671
+ value: function declaresItemPreview() {
6672
+ return this.previewInput !== null;
6673
+ }
6674
+ }, {
6675
+ key: "executeSerialize",
6676
+ value: function executeSerialize() {
6677
+ var _this$renderInput, _this$customValidateF;
6678
+ return {
6679
+ type: "locale",
6680
+ render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
6681
+ preview: this.previewInput ? true : undefined,
6682
+ opt: this.opt,
6683
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
6684
+ readonly: this.isReadonly,
6685
+ hidden: this.isHidden,
6686
+ description: this.description
6687
+ };
6688
+ }
6689
+ }, {
6690
+ key: "executePreview",
6691
+ value: function executePreview() {
6692
+ return {};
6693
+ }
6694
+ }]);
6695
+ }(Schema);
6696
+
6697
+ /**
6698
+ * Define one of the project's languages.
6699
+ *
6700
+ * The languages themselves are declared in the settings module, under
6701
+ * `locales.available` — this says only that a value is one of them.
6702
+ *
6703
+ * @example // a field: everything under this object is in this language
6704
+ * const schema = s.object({ locale: s.locale(), title: s.string() });
6705
+ *
6706
+ * @example // a key: one entry per language
6707
+ * const schema = s.record(s.locale(), s.object({ title: s.string() }));
6708
+ */
6709
+ var locale = function locale() {
6710
+ return new LocaleSchema();
6711
+ };
6712
+
5995
6713
  var BooleanSchema = /*#__PURE__*/function (_Schema) {
5996
6714
  function BooleanSchema() {
5997
6715
  var _this;
@@ -6109,7 +6827,7 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
6109
6827
  }, {
6110
6828
  key: "nullable",
6111
6829
  value: function nullable() {
6112
- return new BooleanSchema(true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
6830
+ return new BooleanSchema(true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
6113
6831
  }
6114
6832
  }, {
6115
6833
  key: "readonly",
@@ -6205,6 +6923,99 @@ var _boolean = function _boolean() {
6205
6923
  return new BooleanSchema();
6206
6924
  };
6207
6925
 
6926
+ /**
6927
+ * Language tags, and what makes one wrong.
6928
+ *
6929
+ * Val does not ship a list of locales. Which languages a project publishes is a
6930
+ * property of that project, so it is declared in the settings module — see
6931
+ * `LocalesSettingsSource` — and everything downstream reads it from there.
6932
+ *
6933
+ * What Val does own is the SPELLING. A tag is checked against BCP 47
6934
+ * (RFC 5646) through `Intl.getCanonicalLocales`, which is the same
6935
+ * implementation the browser, `<html lang>` and every `Intl` constructor use.
6936
+ * Delegating rather than writing a matcher is the point: a tag this accepts is
6937
+ * a tag those accept.
6938
+ */
6939
+
6940
+ /**
6941
+ * What is wrong with `tag` as a language tag, or `false` if nothing is.
6942
+ *
6943
+ * Canonical form, not merely parseable, and the difference is what makes this
6944
+ * worth checking at all. `nb-no` parses; `Intl.DisplayNames` and a
6945
+ * case-sensitive comparison against a stored key do not agree about it. Since a
6946
+ * locale is compared as a string everywhere — a record key, a URL segment, a
6947
+ * value in content — one spelling has to win, and the canonical one is the
6948
+ * spelling every other tool already produces.
6949
+ *
6950
+ * The message names the canonical form where there is one, because "not
6951
+ * canonical" is not an instruction and `nb-NO` is.
6952
+ */
6953
+ function localeTagError(tag) {
6954
+ var canonical;
6955
+ try {
6956
+ canonical = Intl.getCanonicalLocales(tag);
6957
+ } catch (_unused) {
6958
+ // RangeError, for anything the grammar rejects: an underscore instead of a
6959
+ // hyphen (`nb_NO`, which is POSIX rather than BCP 47), an empty subtag, a
6960
+ // subtag of the wrong length.
6961
+ return "'".concat(tag, "' is not a language tag. Language then region, separated by a hyphen \u2014 'nb-NO', not 'nb_NO'");
6962
+ }
6963
+ if (canonical.length !== 1) {
6964
+ // A comma-separated list, or something that canonicalised to nothing.
6965
+ return "'".concat(tag, "' is not a single language tag");
6966
+ }
6967
+ if (canonical[0] !== tag) {
6968
+ return "'".concat(tag, "' is not canonical. Write it as '").concat(canonical[0], "'");
6969
+ }
6970
+ return false;
6971
+ }
6972
+
6973
+ /**
6974
+ * A language tag, as content holds it.
6975
+ *
6976
+ * A *flavoured* string rather than a union or a strict brand. Which languages a
6977
+ * project has is declared in its settings module, where the project can change
6978
+ * it, so there is no set for a type to enumerate — and a strict brand would make
6979
+ * `"nb-NO"` unassignable, which would mean writing every locale in a `.val.ts`
6980
+ * through a constructor. Content stays plain data.
6981
+ *
6982
+ * So this carries no compile-time guarantee, and is not meant to. It names the
6983
+ * concept where a bare `string` would say nothing, and the guarantee is the
6984
+ * `locale:check-locale` validation against `locales.available`.
6985
+ */
6986
+
6987
+ /**
6988
+ * The locale a stored value means, or `null` if it means none of them.
6989
+ *
6990
+ * A lookup against the project's languages, and today that is all it is. It
6991
+ * stays a named function because it is the one place the question is asked —
6992
+ * the Studio, the validation worker and the server all come here rather than
6993
+ * comparing strings themselves, so they cannot disagree about what a stored
6994
+ * value is.
6995
+ */
6996
+ function localeOfValue(value, available) {
6997
+ return available.includes(value) ? value : null;
6998
+ }
6999
+
7000
+ /**
7001
+ * A rule about a section that its individual fields cannot state.
7002
+ *
7003
+ * Paths are WITHIN the section, so an error lands on the value it is about —
7004
+ * including a row of a list, which is what makes this different from a
7005
+ * `.validate()` on the field.
7006
+ */
7007
+
7008
+ /**
7009
+ * Every section's rules, by the name that travels in the serialized schema.
7010
+ *
7011
+ * Typed with `| undefined` on the value rather than as a `Partial`: the whole
7012
+ * point is that a lookup can miss, because the name comes off a serialized
7013
+ * schema that may have been written by a newer Val than the one reading it.
7014
+ */
7015
+ var sectionValidators = {
7016
+ locales: localesSectionErrors
7017
+ };
7018
+
6208
7019
  /**
6209
7020
  * An object whose keys are all optional: absent means unset.
6210
7021
  *
@@ -6223,6 +7034,23 @@ var SettingsSchema = /*#__PURE__*/function (_Schema) {
6223
7034
  var isReadonly = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
6224
7035
  var isHidden = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
6225
7036
  var description = arguments.length > 4 ? arguments[4] : undefined;
7037
+ var
7038
+ /**
7039
+ * Which section this is, where Val has rules about it beyond its keys.
7040
+ *
7041
+ * Not the `validate` the class deliberately does not offer: that one is the
7042
+ * schema author's, and `s.settings()` takes no arguments to declare it
7043
+ * with. This names a rule Val states about a shape Val owns — no language
7044
+ * declared twice in `locales.available` is true of every project, and
7045
+ * there is nowhere else it can be said. A single value's rules stay on its
7046
+ * own schema; this is for the ones that need to see more than one value,
7047
+ * or to report on a row of a list.
7048
+ *
7049
+ * A NAME rather than the function, so it survives serialization: the schema
7050
+ * reaches the Studio's validation worker as JSON, and a closure would be
7051
+ * dropped on the way — which is how these rules once went missing there.
7052
+ */
7053
+ section = arguments.length > 5 ? arguments[5] : undefined;
6226
7054
  _classCallCheck(this, SettingsSchema);
6227
7055
  _this = _callSuper(this, SettingsSchema);
6228
7056
  _this.items = items;
@@ -6230,10 +7058,24 @@ var SettingsSchema = /*#__PURE__*/function (_Schema) {
6230
7058
  _this.isReadonly = isReadonly;
6231
7059
  _this.isHidden = isHidden;
6232
7060
  _this.description = description;
7061
+ _this.section = section;
6233
7062
  return _this;
6234
7063
  }
7064
+
7065
+ /**
7066
+ * This section's rules, or `undefined` where there are none to run.
7067
+ *
7068
+ * A name this Val does not know means a schema written by a newer one. Its
7069
+ * per-field validation still runs; only the section's own rule is missed,
7070
+ * which is the mild half of the failure and better than refusing the schema.
7071
+ */
6235
7072
  _inherits(SettingsSchema, _Schema);
6236
7073
  return _createClass(SettingsSchema, [{
7074
+ key: "sectionValidate",
7075
+ value: function sectionValidate() {
7076
+ return this.section === undefined ? undefined : sectionValidators[this.section];
7077
+ }
7078
+ }, {
6237
7079
  key: "executeValidate",
6238
7080
  value: function executeValidate(path, src) {
6239
7081
  var error = false;
@@ -6286,6 +7128,39 @@ var SettingsSchema = /*#__PURE__*/function (_Schema) {
6286
7128
  }).join(", ")), src, true);
6287
7129
  }
6288
7130
  }
7131
+ var sectionValidate = this.sectionValidate();
7132
+ if (sectionValidate) {
7133
+ var _iterator = _createForOfIteratorHelper(sectionValidate(src)),
7134
+ _step;
7135
+ try {
7136
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
7137
+ var _ref4;
7138
+ var _step$value = _step.value,
7139
+ keys = _step$value.path,
7140
+ message = _step$value.message;
7141
+ var _subPath = path;
7142
+ var _iterator2 = _createForOfIteratorHelper(keys),
7143
+ _step2;
7144
+ try {
7145
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
7146
+ var _key3 = _step2.value;
7147
+ _subPath = _subPath && createValPathOfItem(_subPath, _key3);
7148
+ }
7149
+ } catch (err) {
7150
+ _iterator2.e(err);
7151
+ } finally {
7152
+ _iterator2.f();
7153
+ }
7154
+ error = this.appendValidationError(error, // Falls back to the section itself, which is where an error belongs
7155
+ // when the value it is about is not addressable.
7156
+ (_ref4 = _subPath) !== null && _ref4 !== void 0 ? _ref4 : path, message, src);
7157
+ }
7158
+ } catch (err) {
7159
+ _iterator.e(err);
7160
+ } finally {
7161
+ _iterator.f();
7162
+ }
7163
+ }
6289
7164
  return error;
6290
7165
  }
6291
7166
  }, {
@@ -6331,17 +7206,17 @@ var SettingsSchema = /*#__PURE__*/function (_Schema) {
6331
7206
  }, {
6332
7207
  key: "nullable",
6333
7208
  value: function nullable() {
6334
- return new SettingsSchema(this.items, true, this.isReadonly, this.isHidden, this.description);
7209
+ return new SettingsSchema(this.items, true, this.isReadonly, this.isHidden, this.description, this.section);
6335
7210
  }
6336
7211
  }, {
6337
7212
  key: "readonly",
6338
7213
  value: function readonly() {
6339
- return new SettingsSchema(this.items, this.opt, true, this.isHidden, this.description);
7214
+ return new SettingsSchema(this.items, this.opt, true, this.isHidden, this.description, this.section);
6340
7215
  }
6341
7216
  }, {
6342
7217
  key: "hidden",
6343
7218
  value: function hidden() {
6344
- return new SettingsSchema(this.items, this.opt, this.isReadonly, true, this.description);
7219
+ return new SettingsSchema(this.items, this.opt, this.isReadonly, true, this.description, this.section);
6345
7220
  }
6346
7221
  }, {
6347
7222
  key: "executeCustomValidateAt",
@@ -6356,16 +7231,17 @@ var SettingsSchema = /*#__PURE__*/function (_Schema) {
6356
7231
  value: function executeSerialize() {
6357
7232
  return {
6358
7233
  type: "settings",
6359
- items: Object.fromEntries(Object.entries(this.items).map(function (_ref4) {
6360
- var _ref5 = _slicedToArray(_ref4, 2),
6361
- key = _ref5[0],
6362
- schema = _ref5[1];
7234
+ items: Object.fromEntries(Object.entries(this.items).map(function (_ref5) {
7235
+ var _ref6 = _slicedToArray(_ref5, 2),
7236
+ key = _ref6[0],
7237
+ schema = _ref6[1];
6363
7238
  return [key, schema["executeSerialize"]()];
6364
7239
  })),
6365
7240
  opt: this.opt,
6366
7241
  readonly: this.isReadonly,
6367
7242
  hidden: this.isHidden,
6368
- description: this.description
7243
+ description: this.description,
7244
+ section: this.section
6369
7245
  };
6370
7246
  }
6371
7247
  }, {
@@ -6375,19 +7251,19 @@ var SettingsSchema = /*#__PURE__*/function (_Schema) {
6375
7251
  if (src === null) {
6376
7252
  return res;
6377
7253
  }
6378
- for (var _key3 in this.items) {
6379
- var itemSrc = src[_key3];
7254
+ for (var _key4 in this.items) {
7255
+ var itemSrc = src[_key4];
6380
7256
  if (itemSrc === null || itemSrc === undefined) {
6381
7257
  continue;
6382
7258
  }
6383
- var subPath = unsafeCreateSourcePath(sourcePath, _key3);
7259
+ var subPath = unsafeCreateSourcePath(sourcePath, _key4);
6384
7260
  if (scope !== undefined && !scope.wantsUnder(subPath)) {
6385
7261
  continue;
6386
7262
  }
6387
- var itemResult = this.items[_key3]["executePreview"](subPath, itemSrc, scope);
7263
+ var itemResult = this.items[_key4]["executePreview"](subPath, itemSrc, scope);
6388
7264
  for (var keyS in itemResult) {
6389
- var _key4 = keyS;
6390
- res[_key4] = itemResult[_key4];
7265
+ var _key5 = keyS;
7266
+ res[_key5] = itemResult[_key5];
6391
7267
  }
6392
7268
  }
6393
7269
  return res;
@@ -6431,11 +7307,58 @@ function settings() {
6431
7307
  assistant: new SettingsSchema({
6432
7308
  enabled: _boolean().nullable().describe("Whether editors have an assistant in this project. Unset means nobody has decided: it is offered, and turned on when someone accepts."),
6433
7309
  context: string().multiline().maxLength(ASSISTANT_SETTINGS_MAX_LENGTH).nullable().describe("Background the assistant would otherwise have to guess: what this site is, who runs it, names and spellings that matter."),
6434
- tone: string().multiline().maxLength(ASSISTANT_SETTINGS_MAX_LENGTH).nullable().describe("How the assistant should write when it writes content: formal or playful, British or American, how headings are cased.")
6435
- })
7310
+ tone: string().multiline().maxLength(ASSISTANT_SETTINGS_MAX_LENGTH).nullable().describe("How the assistant should write when it writes content: formal or playful, British or American, how headings are cased."),
7311
+ translation: record(locale(), string().multiline().maxLength(ASSISTANT_SETTINGS_MAX_LENGTH).nullable()).nullable().describe("How to translate into each language: dialect, formality, and the words that stay untranslated.")
7312
+ }),
7313
+ locales: new SettingsSchema({
7314
+ // Nullable because the source type is, and because the Studio writes
7315
+ // `null` for every sibling the first time a section is created.
7316
+ available: array(string()).nullable().describe("The languages this project publishes, as BCP 47 tags: en-US, nb-NO. The order is kept: it is the order of the Studio's picker and of a locale-keyed record's rows.")
7317
+ }, false, false, false, undefined, "locales")
6436
7318
  });
6437
7319
  }
6438
7320
 
7321
+ /**
7322
+ * The rules about `locales` that need to see the whole list.
7323
+ *
7324
+ * Two of them, and both report on the ENTRY rather than the list: a tag has to
7325
+ * be spelled canonically, and a language cannot be declared twice. Neither can
7326
+ * live on the item schema — the item sees one string, and "twice" is a fact
7327
+ * about its siblings — and neither can be a `.validate()` on the array either,
7328
+ * since that reports one message on the array itself rather than on the row to
7329
+ * delete.
7330
+ *
7331
+ * Reads defensively rather than asserting the source's type. A settings module
7332
+ * is a file someone edits by hand, and validation runs against whatever is in
7333
+ * it — including the shapes the per-key pass is, in the same breath, reporting.
7334
+ */
7335
+ function localesSectionErrors(src) {
7336
+ var errors = [];
7337
+ var raw = Array.isArray(src["available"]) ? src["available"] : [];
7338
+ var seen = new Set();
7339
+ for (var i = 0; i < raw.length; i++) {
7340
+ var tag = raw[i];
7341
+ if (typeof tag !== "string") {
7342
+ // The item's own schema has already said what is wrong with it.
7343
+ continue;
7344
+ }
7345
+ var spelling = localeTagError(tag);
7346
+ if (spelling !== false) {
7347
+ errors.push({
7348
+ path: ["available", i],
7349
+ message: spelling
7350
+ });
7351
+ } else if (seen.has(tag)) {
7352
+ errors.push({
7353
+ path: ["available", i],
7354
+ message: "'".concat(tag, "' is declared twice")
7355
+ });
7356
+ }
7357
+ seen.add(tag);
7358
+ }
7359
+ return errors;
7360
+ }
7361
+
6439
7362
  /**
6440
7363
  * What may be WRITTEN as an external record's source, on top of the marker.
6441
7364
  *
@@ -7149,7 +8072,7 @@ var NumberSchema = /*#__PURE__*/function (_Schema) {
7149
8072
  }, {
7150
8073
  key: "nullable",
7151
8074
  value: function nullable() {
7152
- return new NumberSchema(this.options, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
8075
+ return new NumberSchema(this.options, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
7153
8076
  }
7154
8077
  }, {
7155
8078
  key: "readonly",
@@ -7286,6 +8209,15 @@ var number = function number(options) {
7286
8209
  * discriminated union's variants and must not try to recurse into these.
7287
8210
  */
7288
8211
  var EnumSchema = /*#__PURE__*/function (_Schema) {
8212
+ /**
8213
+ * Type-only marker: as a record key, this declares the key set.
8214
+ *
8215
+ * An enum names every value it may take, so a record keyed by one holds
8216
+ * exactly those keys — the same claim `s.literal()` and `s.locale()` make.
8217
+ * `DiscriminatedUnionSchema` carries no marker: it discriminates objects and
8218
+ * cannot be a record key at all. See `LocaleSchema`.
8219
+ */
8220
+
7289
8221
  function EnumSchema(values) {
7290
8222
  var _this;
7291
8223
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
@@ -7439,7 +8371,7 @@ var EnumSchema = /*#__PURE__*/function (_Schema) {
7439
8371
  key: "nullable",
7440
8372
  value: function nullable() {
7441
8373
  // Explicit type args: `previewInput` would otherwise pin inference to `Src`.
7442
- return new EnumSchema(this.values, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
8374
+ return new EnumSchema(this.values, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
7443
8375
  }
7444
8376
  }, {
7445
8377
  key: "readonly",
@@ -7830,7 +8762,7 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
7830
8762
  }, {
7831
8763
  key: "nullable",
7832
8764
  value: function nullable() {
7833
- return new KeyOfSchema(this.schema, this.sourcePath, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
8765
+ return new KeyOfSchema(this.schema, this.sourcePath, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
7834
8766
  }
7835
8767
  }, {
7836
8768
  key: "readonly",
@@ -8378,7 +9310,7 @@ function file(options) {
8378
9310
  }
8379
9311
 
8380
9312
  /**
8381
- * Options for s.files()
9313
+ * Options for s.fileset()
8382
9314
  */
8383
9315
 
8384
9316
  /**
@@ -8392,9 +9324,9 @@ function file(options) {
8392
9324
  *
8393
9325
  * @example
8394
9326
  * ```typescript
8395
- * const schema = s.files({
9327
+ * const schema = s.fileset({
8396
9328
  * accept: "application/pdf",
8397
- * directory: "/public/val/documents",
9329
+ * dir: "/public/val/documents",
8398
9330
  * });
8399
9331
  * export default c.define("/content/documents.val.ts", schema, {
8400
9332
  * "/public/val/documents/report.pdf": {
@@ -8403,15 +9335,15 @@ function file(options) {
8403
9335
  * });
8404
9336
  * ```
8405
9337
  */
8406
- var files = function files(options) {
8407
- var directory = options.directory;
9338
+ var fileset = function fileset(options) {
9339
+ var dir = options.dir;
8408
9340
  var itemSchema = new ObjectSchema({
8409
9341
  mimeType: new StringSchema({}, false)
8410
9342
  }, false);
8411
9343
  return new RecordSchema(itemSchema, false, [], null, null, {
8412
9344
  type: "files",
8413
9345
  accept: options.accept,
8414
- directory: directory,
9346
+ dir: dir,
8415
9347
  remote: false
8416
9348
  });
8417
9349
  };
@@ -8604,7 +9536,7 @@ var DateSchema = /*#__PURE__*/function (_Schema) {
8604
9536
  }, {
8605
9537
  key: "nullable",
8606
9538
  value: function nullable() {
8607
- return new DateSchema(this.options, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
9539
+ return new DateSchema(this.options, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
8608
9540
  }
8609
9541
  }, {
8610
9542
  key: "readonly",
@@ -8940,7 +9872,7 @@ var DateTimeSchema = /*#__PURE__*/function (_Schema) {
8940
9872
  }, {
8941
9873
  key: "nullable",
8942
9874
  value: function nullable() {
8943
- return new DateTimeSchema(this.options, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
9875
+ return new DateTimeSchema(this.options, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
8944
9876
  }
8945
9877
  }, {
8946
9878
  key: "readonly",
@@ -9188,7 +10120,7 @@ var CodeSchema = /*#__PURE__*/function (_Schema) {
9188
10120
  }, {
9189
10121
  key: "nullable",
9190
10122
  value: function nullable() {
9191
- return new CodeSchema(this.options, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
10123
+ return new CodeSchema(this.options, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
9192
10124
  }
9193
10125
  }, {
9194
10126
  key: "readonly",
@@ -9936,7 +10868,7 @@ var ColorSchema = /*#__PURE__*/function (_Schema) {
9936
10868
  }, {
9937
10869
  key: "nullable",
9938
10870
  value: function nullable() {
9939
- return new ColorSchema(this.options, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
10871
+ return new ColorSchema(this.options, true, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
9940
10872
  }
9941
10873
  }, {
9942
10874
  key: "readonly",
@@ -10042,14 +10974,37 @@ function router(router, keyOrItem, maybeItem) {
10042
10974
  */
10043
10975
 
10044
10976
  /**
10045
- * Options for s.images()
10977
+ * What an entry's `alt` holds, for a given `alt` schema.
10978
+ *
10979
+ * This is the schema's own source type, not a second list that has to be kept
10980
+ * in step with `AltSchema`: `s.string()` gives `string`, `s.string().nullable()`
10981
+ * gives `string | null`, and `s.record(s.string())` gives
10982
+ * `Record<string, string>`.
10046
10983
  */
10047
10984
 
10985
+ /** Every `alt` value any `AltSchema` can produce. */
10986
+
10048
10987
  /**
10049
- * Metadata for an image entry in the images record
10988
+ * Options for s.imageset()
10050
10989
  */
10051
10990
 
10052
- // Item schema types for images (alt simplified to string | null for typing)
10991
+ /**
10992
+ * `alt` is optional only when it is the default schema.
10993
+ *
10994
+ * Naming a different `Alt` and then leaving `alt` out would make the fallback
10995
+ * in `imageset()` a lie — `Alt` would say `s.string()` while the value was a
10996
+ * nullable one. Requiring it in that case is what makes the fallback sound:
10997
+ * the branch that uses it is reachable only when `Alt` IS the default.
10998
+ */
10999
+
11000
+ /**
11001
+ * Metadata for an image entry in the images record.
11002
+ *
11003
+ * `alt` follows the schema's `alt` option, so it defaults to `string | null`
11004
+ * and becomes `string` under `s.string()` or `Record<string, string>` under
11005
+ * `s.record(s.string())`. Write `ImagesetEntryMetadata<AltSource>` where a
11006
+ * gallery of any alt shape is acceptable.
11007
+ */
10053
11008
 
10054
11009
  /**
10055
11010
  * Define a collection of images.
@@ -10060,9 +11015,9 @@ function router(router, keyOrItem, maybeItem) {
10060
11015
  *
10061
11016
  * @example
10062
11017
  * ```typescript
10063
- * const schema = s.images({
11018
+ * const schema = s.imageset({
10064
11019
  * accept: "image/webp",
10065
- * directory: "/public/val/images",
11020
+ * dir: "/public/val/images",
10066
11021
  * alt: s.string().minLength(4),
10067
11022
  * });
10068
11023
  * export default c.define("/content/images.val.ts", schema, {
@@ -10075,9 +11030,18 @@ function router(router, keyOrItem, maybeItem) {
10075
11030
  * });
10076
11031
  * ```
10077
11032
  */
10078
- var images = function images(options) {
11033
+ var imageset = function imageset(options) {
10079
11034
  var _options$alt, _options$accept;
10080
- var directory = options.directory;
11035
+ var dir = options.dir;
11036
+ // `options.alt` is `Alt | undefined`, and the fallback is exactly the schema
11037
+ // `Alt` defaults to when `alt` is omitted. TypeScript will not narrow a type
11038
+ // parameter from the absence of a value, so it cannot see that the two agree,
11039
+ // and the fallback is asserted here.
11040
+ //
11041
+ // Sound, not merely convenient: `ImagesetAltOption` makes `alt` REQUIRED
11042
+ // unless `Alt` is the default, so this branch is unreachable for any other
11043
+ // `Alt`. The one assertion in this file, and it replaces the wider one that
11044
+ // used to sit on the ObjectSchema below.
10081
11045
  var altSchema = (_options$alt = options.alt) !== null && _options$alt !== void 0 ? _options$alt : string().nullable();
10082
11046
  var itemSchema = new ObjectSchema({
10083
11047
  width: new NumberSchema(undefined, false),
@@ -10088,7 +11052,7 @@ var images = function images(options) {
10088
11052
  return new RecordSchema(itemSchema, false, [], null, null, {
10089
11053
  type: "images",
10090
11054
  accept: (_options$accept = options.accept) !== null && _options$accept !== void 0 ? _options$accept : "image/*",
10091
- directory: directory,
11055
+ dir: dir,
10092
11056
  remote: false,
10093
11057
  altSchema: altSchema,
10094
11058
  encode: options.encode
@@ -10120,14 +11084,15 @@ function initSchema() {
10120
11084
  keyOf: keyOf,
10121
11085
  record: record,
10122
11086
  file: file,
10123
- files: files,
11087
+ fileset: fileset,
10124
11088
  date: date,
10125
11089
  datetime: datetime,
10126
11090
  color: color,
10127
11091
  code: code,
11092
+ locale: locale,
10128
11093
  route: route,
10129
11094
  router: router,
10130
- images: images,
11095
+ imageset: imageset,
10131
11096
  settings: settings
10132
11097
  // i18n: i18n(locales),
10133
11098
  };
@@ -10263,6 +11228,8 @@ var Hash = /*#__PURE__*/function () {
10263
11228
  _defineProperty(this, "F", 0x9b05688c | 0);
10264
11229
  _defineProperty(this, "G", 0x1f83d9ab | 0);
10265
11230
  _defineProperty(this, "H", 0x5be0cd19 | 0);
11231
+ _defineProperty(this, "_byte", void 0);
11232
+ _defineProperty(this, "_word", void 0);
10266
11233
  _defineProperty(this, "_size", 0);
10267
11234
  _defineProperty(this, "_sp", 0);
10268
11235
  if (!sharedBuffer || sharedOffset >= N.allocTotal) {
@@ -10967,7 +11934,7 @@ function _extractValModules() {
10967
11934
  * The one answer to that question. There used to be two — `hasRemoteFileSchema`
10968
11935
  * in the server, gating whether `/save` demands remote credentials, and
10969
11936
  * `findRequiredRemoteFiles` in the Studio, gating the `/remote/settings` fetch —
10970
- * and they disagreed about `s.images({ ... }).remote()`: the Studio's version
11937
+ * and they disagreed about `s.imageset({ ... }).remote()`: the Studio's version
10971
11938
  * counted a remote media record, the server's did not, because a media
10972
11939
  * collection serializes as a `record` of metadata rather than as an image
10973
11940
  * schema.
@@ -11007,7 +11974,7 @@ function hasRemoteFileSchema(schema) {
11007
11974
  return hasRemoteFileSchema(schema.item);
11008
11975
  } else if (schema.type === "record") {
11009
11976
  /**
11010
- * A media collection — `s.images()` / `s.files()` — is the case both of the
11977
+ * A media collection — `s.imageset()` / `s.fileset()` — is the case both of the
11011
11978
  * old functions were written around, and the one they disagreed on.
11012
11979
  *
11013
11980
  * It has no file or image schema inside it to find: `item` is an object of
@@ -11049,7 +12016,7 @@ function hasRemoteFileSchema(schema) {
11049
12016
  return false;
11050
12017
  } else if (schema.type === "boolean" ||
11051
12018
  // An enum's values are strings, so there is nothing to look inside.
11052
- schema.type === "enum" || schema.type === "number" || schema.type === "string" || schema.type === "literal" || schema.type === "date" || schema.type === "dateTime" || schema.type === "color" || schema.type === "code" || schema.type === "keyOf" || schema.type === "route") {
12019
+ schema.type === "enum" || schema.type === "number" || schema.type === "string" || schema.type === "literal" || schema.type === "date" || schema.type === "dateTime" || schema.type === "color" || schema.type === "code" || schema.type === "keyOf" || schema.type === "route" || schema.type === "locale") {
11053
12020
  return false;
11054
12021
  } else {
11055
12022
  var exhaustiveCheck = schema;
@@ -11067,8 +12034,8 @@ function hasRemoteFileSchema(schema) {
11067
12034
  *
11068
12035
  * It is a walk over the SERIALIZED schema for the reasons given above, and for
11069
12036
  * one more that is specific to this question: the two cases most likely to be
11070
- * missed are invisible to a value type. A media collection (`s.images()` /
11071
- * `s.files()`) serializes as a record of metadata with no image schema inside
12037
+ * missed are invisible to a value type. A media collection (`s.imageset()` /
12038
+ * `s.fileset()`) serializes as a record of metadata with no image schema inside
11072
12039
  * it, and a richtext inline image lives in a constructor argument. A check
11073
12040
  * written against the item TYPE would silently pass both — and the gallery case
11074
12041
  * already has a data-loss incident attached to it (see above).
@@ -11121,7 +12088,7 @@ function hasMediaSchema(schema) {
11121
12088
  return false;
11122
12089
  } else if (schema.type === "boolean" ||
11123
12090
  // An enum's values are strings, so there is nothing to look inside.
11124
- schema.type === "enum" || schema.type === "number" || schema.type === "string" || schema.type === "literal" || schema.type === "date" || schema.type === "dateTime" || schema.type === "color" || schema.type === "code" || schema.type === "keyOf" || schema.type === "route" ||
12091
+ schema.type === "enum" || schema.type === "number" || schema.type === "string" || schema.type === "literal" || schema.type === "date" || schema.type === "dateTime" || schema.type === "color" || schema.type === "code" || schema.type === "keyOf" || schema.type === "route" || schema.type === "locale" ||
11125
12092
  // A settings module holds the assistant's configuration, not content, and
11126
12093
  // nothing in it is media.
11127
12094
  schema.type === "settings") {
@@ -11400,6 +12367,46 @@ function getFileHash(text) {
11400
12367
  return hashToRemoteFileHash(getSHA256Hash(new Uint8Array(text)));
11401
12368
  }
11402
12369
 
12370
+ /**
12371
+ * The variant of a discriminated union that a value takes, by its tag.
12372
+ *
12373
+ * A discriminated union is a fork rather than a level: the variant IS the node,
12374
+ * and everything a caller wants to know about that node — its fields, its
12375
+ * `locale` field, the schema to draw it with — is on the variant and not on the
12376
+ * union. Resolving it takes the source, so it cannot be done from the schema
12377
+ * alone, which is why every caller that has only the union ends up needing this.
12378
+ *
12379
+ * `undefined` where the tag matches nothing, rather than a fallback to the first
12380
+ * variant: a value whose tag names no variant is not a member of the union,
12381
+ * validation is already saying so, and reading fields out of the wrong shape
12382
+ * would answer confidently and wrongly.
12383
+ *
12384
+ * `s.enum()` never reaches here — it is a leaf whose values are strings, with no
12385
+ * variants to resolve — so anything that is not a discriminated union answers
12386
+ * `undefined` too.
12387
+ */
12388
+ function discriminatedUnionBranchOf(schema, tag) {
12389
+ if ((schema === null || schema === void 0 ? void 0 : schema.type) !== "discriminated-union") {
12390
+ return undefined;
12391
+ }
12392
+ var _iterator = _createForOfIteratorHelper(schema.items),
12393
+ _step;
12394
+ try {
12395
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
12396
+ var item = _step.value;
12397
+ var discriminator = item.items[schema.key];
12398
+ if ((discriminator === null || discriminator === void 0 ? void 0 : discriminator.type) === "literal" && discriminator.value === tag) {
12399
+ return item;
12400
+ }
12401
+ }
12402
+ } catch (err) {
12403
+ _iterator.e(err);
12404
+ } finally {
12405
+ _iterator.f();
12406
+ }
12407
+ return undefined;
12408
+ }
12409
+
11403
12410
  function deserializeSchema(serialized) {
11404
12411
  var schema = deserializeSchemaImpl(serialized);
11405
12412
  if (serialized.readonly) {
@@ -11411,7 +12418,7 @@ function deserializeSchema(serialized) {
11411
12418
  return schema;
11412
12419
  }
11413
12420
  function deserializeSchemaImpl(serialized) {
11414
- var _serialized$options, _serialized$options2, _serialized$render, _serialized$multiline, _serialized$render2, _serialized$render3, _serialized$render4, _serialized$render5, _serialized$render6, _serialized$render7, _serialized$render8, _serialized$accept, _serialized$directory, _serialized$remote, _serialized$jsonValue, _serialized$render0, _serialized$external, _serialized$render1, _serialized$render11, _serialized$render12, _serialized$render13, _serialized$render14, _serialized$render15, _serialized$render16;
12421
+ var _serialized$options, _serialized$options2, _serialized$render, _serialized$multiline, _serialized$render2, _serialized$render3, _serialized$render4, _serialized$render5, _serialized$render6, _serialized$render7, _serialized$render8, _serialized$accept, _serialized$dir, _serialized$remote, _serialized$jsonValue, _serialized$render0, _serialized$external, _serialized$render1, _serialized$render12, _serialized$render13, _serialized$render14, _serialized$render15, _serialized$render16, _serialized$render17;
11415
12422
  switch (serialized.type) {
11416
12423
  case "string":
11417
12424
  return new StringSchema(_objectSpread2(_objectSpread2({}, serialized.options), {}, {
@@ -11440,7 +12447,12 @@ function deserializeSchemaImpl(serialized) {
11440
12447
  key = _ref4[0],
11441
12448
  item = _ref4[1];
11442
12449
  return [key, deserializeSchema(item)];
11443
- })), serialized.opt, false, false, serialized.description);
12450
+ })), serialized.opt, false, false, serialized.description,
12451
+ // Carried through, or the Studio's validation worker — which only ever
12452
+ // sees the deserialized schema — would run every field's own rules and
12453
+ // none of the section's, so a language declared twice would be reported
12454
+ // by the CLI and silently accepted in the Studio.
12455
+ serialized.section);
11444
12456
  case "array":
11445
12457
  return new ArraySchema(deserializeSchema(serialized.item), serialized.opt, [], false, false, serialized.description,
11446
12458
  // The preview closure cannot survive serialization; the render can.
@@ -11466,7 +12478,7 @@ function deserializeSchemaImpl(serialized) {
11466
12478
  return new RecordSchema(deserializeSchema(serialized.item), serialized.opt, [], null, serialized.key ? deserializeSchema(serialized.key) : null, serialized.mediaType ? {
11467
12479
  type: serialized.mediaType,
11468
12480
  accept: (_serialized$accept = serialized.accept) !== null && _serialized$accept !== void 0 ? _serialized$accept : "*/*",
11469
- directory: (_serialized$directory = serialized.directory) !== null && _serialized$directory !== void 0 ? _serialized$directory : "/public/val",
12481
+ dir: (_serialized$dir = serialized.dir) !== null && _serialized$dir !== void 0 ? _serialized$dir : "/public/val",
11470
12482
  remote: (_serialized$remote = serialized.remote) !== null && _serialized$remote !== void 0 ? _serialized$remote : false,
11471
12483
  altSchema: serialized.alt ? deserializeSchema(serialized.alt) : undefined
11472
12484
  } : undefined, false, false, serialized.description, (_serialized$jsonValue = serialized.jsonValues) !== null && _serialized$jsonValue !== void 0 ? _serialized$jsonValue : false,
@@ -11477,27 +12489,32 @@ function deserializeSchemaImpl(serialized) {
11477
12489
  (_serialized$external = serialized.external) !== null && _serialized$external !== void 0 ? _serialized$external : null);
11478
12490
  case "keyOf":
11479
12491
  return new KeyOfSchema(serialized.schema, serialized.path, serialized.opt, [], false, false, serialized.description, (_serialized$render1 = serialized.render) !== null && _serialized$render1 !== void 0 ? _serialized$render1 : null);
11480
- case "route":
12492
+ case "locale":
11481
12493
  {
11482
12494
  var _serialized$render10;
12495
+ return new LocaleSchema(serialized.opt, [], false, false, serialized.description, (_serialized$render10 = serialized.render) !== null && _serialized$render10 !== void 0 ? _serialized$render10 : null);
12496
+ }
12497
+ case "route":
12498
+ {
12499
+ var _serialized$render11;
11483
12500
  var routeOptions = serialized.options ? {
11484
12501
  include: serialized.options.include ? new RegExp(serialized.options.include.source, serialized.options.include.flags) : undefined,
11485
12502
  exclude: serialized.options.exclude ? new RegExp(serialized.options.exclude.source, serialized.options.exclude.flags) : undefined
11486
12503
  } : undefined;
11487
- return new RouteSchema(routeOptions, serialized.opt, [], false, false, serialized.description, (_serialized$render10 = serialized.render) !== null && _serialized$render10 !== void 0 ? _serialized$render10 : null);
12504
+ return new RouteSchema(routeOptions, serialized.opt, [], false, false, serialized.description, (_serialized$render11 = serialized.render) !== null && _serialized$render11 !== void 0 ? _serialized$render11 : null);
11488
12505
  }
11489
12506
  case "file":
11490
- return new FileSchema(serialized.options, serialized.opt, serialized.remote, [], {}, false, false, serialized.description, (_serialized$render11 = serialized.render) !== null && _serialized$render11 !== void 0 ? _serialized$render11 : null);
12507
+ return new FileSchema(serialized.options, serialized.opt, serialized.remote, [], {}, false, false, serialized.description, (_serialized$render12 = serialized.render) !== null && _serialized$render12 !== void 0 ? _serialized$render12 : null);
11491
12508
  case "image":
11492
- return new ImageSchema(serialized.options, serialized.opt, serialized.remote, [], {}, false, false, serialized.description, (_serialized$render12 = serialized.render) !== null && _serialized$render12 !== void 0 ? _serialized$render12 : null);
12509
+ return new ImageSchema(serialized.options, serialized.opt, serialized.remote, [], {}, false, false, serialized.description, (_serialized$render13 = serialized.render) !== null && _serialized$render13 !== void 0 ? _serialized$render13 : null);
11493
12510
  case "date":
11494
- return new DateSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$render13 = serialized.render) !== null && _serialized$render13 !== void 0 ? _serialized$render13 : null);
12511
+ return new DateSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$render14 = serialized.render) !== null && _serialized$render14 !== void 0 ? _serialized$render14 : null);
11495
12512
  case "dateTime":
11496
- return new DateTimeSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$render14 = serialized.render) !== null && _serialized$render14 !== void 0 ? _serialized$render14 : null);
12513
+ return new DateTimeSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$render15 = serialized.render) !== null && _serialized$render15 !== void 0 ? _serialized$render15 : null);
11497
12514
  case "color":
11498
- return new ColorSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$render15 = serialized.render) !== null && _serialized$render15 !== void 0 ? _serialized$render15 : null);
12515
+ return new ColorSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$render16 = serialized.render) !== null && _serialized$render16 !== void 0 ? _serialized$render16 : null);
11499
12516
  case "code":
11500
- return new CodeSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$render16 = serialized.render) !== null && _serialized$render16 !== void 0 ? _serialized$render16 : null);
12517
+ return new CodeSchema(serialized.options, serialized.opt, [], false, false, serialized.description, (_serialized$render17 = serialized.render) !== null && _serialized$render17 !== void 0 ? _serialized$render17 : null);
11501
12518
  default:
11502
12519
  {
11503
12520
  var exhaustiveCheck = serialized;
@@ -12164,7 +13181,7 @@ function isPageRouter(routerId) {
12164
13181
 
12165
13182
  var corePackageJson = {
12166
13183
  name: "@valbuild/core",
12167
- version: "0.126.0",
13184
+ version: "0.128.0",
12168
13185
  "private": false,
12169
13186
  description: "Val - supercharged hard-coded content",
12170
13187
  repository: {
@@ -12335,4 +13352,4 @@ function tryJsonParse(str) {
12335
13352
  }
12336
13353
  }
12337
13354
 
12338
- export { parseNextJsRoutePattern as $, ArraySchema as A, BooleanSchema as B, ColorSchema as C, DEFAULT_CONTENT_HOST as D, COLOR_FORMATS as E, FATAL_ERROR_TYPES as F, GenericSelector as G, DEFAULT_COLOR_FORMAT as H, Internal as I, DateTimeSchema as J, KeyOfSchema as K, RouteSchema as L, ModuleFilePathSep as M, NumberSchema as N, ObjectSchema as O, PatchError as P, RichTextSchema as Q, RecordSchema as R, Schema as S, DiscriminatedUnionSchema as T, EnumSchema as U, VAL_EXTENSION as V, LiteralSchema as W, deserializeSchema as X, previewScope as Y, isInlineRender as Z, _typeof as _, _slicedToArray as a, parseTanStackRoutePattern as a0, tanStackSegmentsOfRoutePath as a1, validateUrlAgainstPattern as a2, getSourcePathFromRoute as a3, isPageRouter as a4, _createClass as b, _classCallCheck as c, _toConsumableArray as d, DEFAULT_APP_HOST as e, extractValModules as f, computeValModuleShas as g, hasRemoteFileSchema as h, initVal as i, hasMediaSchema as j, DEFAULT_VAL_REMOTE_HOST as k, derefPatch as l, modules as m, StringSchema as n, ImageSchema as o, FileSchema as p, DateSchema as q, SettingsSchema as r, splitModuleFilePathAndModulePath as s, ASSISTANT_SETTINGS_MAX_LENGTH as t, assistantAvailability as u, SETTINGS_MODULE_CONVENTION as v, isRootModuleFilePath as w, resolveSettingsModule as x, CodeSchema as y, CODE_LANGUAGES as z };
13355
+ export { DiscriminatedUnionSchema as $, ArraySchema as A, BooleanSchema as B, declaredKeySetOf as C, DEFAULT_CONTENT_HOST as D, missingDeclaredKeys as E, FATAL_ERROR_TYPES as F, GenericSelector as G, discriminatedUnionBranchOf as H, Internal as I, ColorSchema as J, CodeSchema as K, LocaleSchema as L, ModuleFilePathSep as M, NumberSchema as N, ObjectSchema as O, PatchError as P, CODE_LANGUAGES as Q, RecordSchema as R, Schema as S, COLOR_FORMATS as T, DEFAULT_COLOR_FORMAT as U, VAL_EXTENSION as V, DateTimeSchema as W, KeyOfSchema as X, RouteSchema as Y, RichTextSchema as Z, _typeof as _, _slicedToArray as a, EnumSchema as a0, LiteralSchema as a1, deserializeSchema as a2, previewScope as a3, isInlineRender as a4, parseNextJsRoutePattern as a5, parseTanStackRoutePattern as a6, tanStackSegmentsOfRoutePath as a7, validateUrlAgainstPattern as a8, getSourcePathFromRoute as a9, isPageRouter as aa, _createClass as b, _classCallCheck as c, _toConsumableArray as d, DEFAULT_APP_HOST as e, extractValModules as f, computeValModuleShas as g, hasRemoteFileSchema as h, initVal as i, hasMediaSchema as j, DEFAULT_VAL_REMOTE_HOST as k, derefPatch as l, modules as m, StringSchema as n, ImageSchema as o, FileSchema as p, DateSchema as q, SettingsSchema as r, splitModuleFilePathAndModulePath as s, ASSISTANT_SETTINGS_MAX_LENGTH as t, assistantAvailability as u, SETTINGS_MODULE_CONVENTION as v, isRootModuleFilePath as w, resolveSettingsModule as x, localeTagError as y, localeOfValue as z };