@valbuild/core 0.120.0 → 0.124.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 (44) hide show
  1. package/CHANGELOG.md +123 -0
  2. package/dist/declarations/src/index.d.ts +12 -1
  3. package/dist/declarations/src/initSchema.d.ts +27 -0
  4. package/dist/declarations/src/initVal.d.ts +13 -8
  5. package/dist/declarations/src/module.d.ts +18 -1
  6. package/dist/declarations/src/schema/array.d.ts +2 -2
  7. package/dist/declarations/src/schema/boolean.d.ts +2 -2
  8. package/dist/declarations/src/schema/code.d.ts +2 -2
  9. package/dist/declarations/src/schema/color.d.ts +2 -2
  10. package/dist/declarations/src/schema/date.d.ts +2 -2
  11. package/dist/declarations/src/schema/datetime.d.ts +2 -2
  12. package/dist/declarations/src/schema/file.d.ts +2 -2
  13. package/dist/declarations/src/schema/files.d.ts +2 -5
  14. package/dist/declarations/src/schema/hasRemoteFileSchema.d.ts +21 -3
  15. package/dist/declarations/src/schema/image.d.ts +2 -2
  16. package/dist/declarations/src/schema/images.d.ts +1 -6
  17. package/dist/declarations/src/schema/index.d.ts +12 -3
  18. package/dist/declarations/src/schema/keyOf.d.ts +2 -2
  19. package/dist/declarations/src/schema/literal.d.ts +2 -2
  20. package/dist/declarations/src/schema/number.d.ts +2 -2
  21. package/dist/declarations/src/schema/object.d.ts +2 -2
  22. package/dist/declarations/src/schema/record.d.ts +80 -4
  23. package/dist/declarations/src/schema/richtext.d.ts +2 -2
  24. package/dist/declarations/src/schema/route.d.ts +2 -2
  25. package/dist/declarations/src/schema/settings.d.ts +102 -0
  26. package/dist/declarations/src/schema/string.d.ts +2 -2
  27. package/dist/declarations/src/schema/union.d.ts +2 -2
  28. package/dist/declarations/src/schema/validation/ValidationFix.d.ts +1 -1
  29. package/dist/declarations/src/selector/index.d.ts +4 -2
  30. package/dist/declarations/src/settingsModule.d.ts +60 -0
  31. package/dist/declarations/src/source/external.d.ts +91 -0
  32. package/dist/declarations/src/source/externalRef.d.ts +46 -0
  33. package/dist/declarations/src/source/index.d.ts +4 -2
  34. package/dist/declarations/src/source/settings.d.ts +94 -0
  35. package/dist/{index-861944d8.cjs.prod.js → index-22a40d42.cjs.prod.js} +1324 -446
  36. package/dist/{index-2f65e194.esm.js → index-9c14df37.esm.js} +1318 -447
  37. package/dist/{index-01f673d2.cjs.dev.js → index-fcd087bd.cjs.dev.js} +1324 -446
  38. package/dist/valbuild-core.cjs.dev.js +8 -1
  39. package/dist/valbuild-core.cjs.prod.js +8 -1
  40. package/dist/valbuild-core.esm.js +1 -1
  41. package/package.json +1 -1
  42. package/patch/dist/valbuild-core-patch.cjs.dev.js +1 -1
  43. package/patch/dist/valbuild-core-patch.cjs.prod.js +1 -1
  44. package/patch/dist/valbuild-core-patch.esm.js +2 -2
@@ -591,12 +591,14 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
591
591
  }, {
592
592
  key: "readonly",
593
593
  value: function readonly() {
594
- return new StringSchema(this.options, this.opt, this.isRaw, this.customValidateFunctions, this.renderInput, true, this.isHidden, this.description, this.previewInput, this.isMultiline);
594
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
595
+ return new StringSchema(this.options, this.opt, this.isRaw, this.customValidateFunctions, this.renderInput, isReadonly, this.isHidden, this.description, this.previewInput, this.isMultiline);
595
596
  }
596
597
  }, {
597
598
  key: "hidden",
598
599
  value: function hidden() {
599
- return new StringSchema(this.options, this.opt, this.isRaw, this.customValidateFunctions, this.renderInput, this.isReadonly, true, this.description, this.previewInput, this.isMultiline);
600
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
601
+ return new StringSchema(this.options, this.opt, this.isRaw, this.customValidateFunctions, this.renderInput, this.isReadonly, isHidden, this.description, this.previewInput, this.isMultiline);
600
602
  }
601
603
  }, {
602
604
  key: "raw",
@@ -869,12 +871,14 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
869
871
  }, {
870
872
  key: "readonly",
871
873
  value: function readonly() {
872
- return new ObjectSchema(this.items, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
874
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
875
+ return new ObjectSchema(this.items, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
873
876
  }
874
877
  }, {
875
878
  key: "hidden",
876
879
  value: function hidden() {
877
- return new ObjectSchema(this.items, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
880
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
881
+ return new ObjectSchema(this.items, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
878
882
  }
879
883
  }, {
880
884
  key: "executeCustomValidateAt",
@@ -1085,12 +1089,14 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
1085
1089
  }, {
1086
1090
  key: "readonly",
1087
1091
  value: function readonly() {
1088
- return new ArraySchema(this.item, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.previewInput, this.renderInput);
1092
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
1093
+ return new ArraySchema(this.item, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.previewInput, this.renderInput);
1089
1094
  }
1090
1095
  }, {
1091
1096
  key: "hidden",
1092
1097
  value: function hidden() {
1093
- return new ArraySchema(this.item, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.previewInput, this.renderInput);
1098
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
1099
+ return new ArraySchema(this.item, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.previewInput, this.renderInput);
1094
1100
  }
1095
1101
  }, {
1096
1102
  key: "executeCustomValidateAt",
@@ -1338,12 +1344,14 @@ var LiteralSchema = /*#__PURE__*/function (_Schema) {
1338
1344
  }, {
1339
1345
  key: "readonly",
1340
1346
  value: function readonly() {
1341
- return new LiteralSchema(this.value, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
1347
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
1348
+ return new LiteralSchema(this.value, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
1342
1349
  }
1343
1350
  }, {
1344
1351
  key: "hidden",
1345
1352
  value: function hidden() {
1346
- return new LiteralSchema(this.value, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
1353
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
1354
+ return new LiteralSchema(this.value, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
1347
1355
  }
1348
1356
  }, {
1349
1357
  key: "executeCustomValidateAt",
@@ -1749,12 +1757,14 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
1749
1757
  }, {
1750
1758
  key: "readonly",
1751
1759
  value: function readonly() {
1752
- return new UnionSchema(this.key, this.items, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
1760
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
1761
+ return new UnionSchema(this.key, this.items, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
1753
1762
  }
1754
1763
  }, {
1755
1764
  key: "hidden",
1756
1765
  value: function hidden() {
1757
- return new UnionSchema(this.key, this.items, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
1766
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
1767
+ return new UnionSchema(this.key, this.items, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
1758
1768
  }
1759
1769
  }, {
1760
1770
  key: "executeCustomValidateAt",
@@ -1954,7 +1964,7 @@ var union = function union(key) {
1954
1964
  return new UnionSchema(key, objects);
1955
1965
  };
1956
1966
 
1957
- var RegEx = /^(https?:\/\/[^/]+)\/file\/p\/([^/]+)\/b\/([^/]+)\/v\/([^/]+)\/h\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
1967
+ var RegEx$1 = /^(https?:\/\/[^/]+)\/file\/p\/([^/]+)\/b\/([^/]+)\/v\/([^/]+)\/h\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
1958
1968
  function splitRemoteRef(ref) {
1959
1969
  if (ref[0] === "/") {
1960
1970
  return {
@@ -1962,7 +1972,7 @@ function splitRemoteRef(ref) {
1962
1972
  error: "Not a remote ref: " + ref
1963
1973
  };
1964
1974
  }
1965
- var match = ref.match(RegEx);
1975
+ var match = ref.match(RegEx$1);
1966
1976
  if (!match) {
1967
1977
  return {
1968
1978
  status: "error",
@@ -3127,12 +3137,14 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
3127
3137
  }, {
3128
3138
  key: "readonly",
3129
3139
  value: function readonly() {
3130
- return new ImageSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, true, this.isHidden, this.description, this.renderInput, this.previewInput);
3140
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
3141
+ return new ImageSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
3131
3142
  }
3132
3143
  }, {
3133
3144
  key: "hidden",
3134
3145
  value: function hidden() {
3135
- return new ImageSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
3146
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
3147
+ return new ImageSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
3136
3148
  }
3137
3149
  }, {
3138
3150
  key: "executeCustomValidateAt",
@@ -3364,12 +3376,14 @@ var RouteSchema = /*#__PURE__*/function (_Schema) {
3364
3376
  }, {
3365
3377
  key: "readonly",
3366
3378
  value: function readonly() {
3367
- return new RouteSchema(this.options, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
3379
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
3380
+ return new RouteSchema(this.options, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
3368
3381
  }
3369
3382
  }, {
3370
3383
  key: "hidden",
3371
3384
  value: function hidden() {
3372
- return new RouteSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
3385
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
3386
+ return new RouteSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
3373
3387
  }
3374
3388
  }, {
3375
3389
  key: "executeCustomValidateAt",
@@ -3948,12 +3962,14 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
3948
3962
  }, {
3949
3963
  key: "readonly",
3950
3964
  value: function readonly() {
3951
- return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
3965
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
3966
+ return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
3952
3967
  }
3953
3968
  }, {
3954
3969
  key: "hidden",
3955
3970
  value: function hidden() {
3956
- return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
3971
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
3972
+ return new RichTextSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
3957
3973
  }
3958
3974
  }, {
3959
3975
  key: "executeCustomValidateAt",
@@ -4354,6 +4370,94 @@ function _resolveJsonValues() {
4354
4370
  return _resolveJsonValues.apply(this, arguments);
4355
4371
  }
4356
4372
 
4373
+ /**
4374
+ * The string used as the `_type` discriminator of an {@link ExternalRecordSrc}.
4375
+ */
4376
+ var EXTERNAL_VAL_EXTENSION_TAG = "external";
4377
+
4378
+ /**
4379
+ * Type-level-only slots. Declared here rather than reusing `PhantomType`
4380
+ * (`source/index.ts`) because three separate facts have to ride along, and that
4381
+ * helper carries one.
4382
+ *
4383
+ * None of them exist at runtime: `c.external()` produces `{ _type: "external" }`
4384
+ * and nothing else.
4385
+ */
4386
+
4387
+ /**
4388
+ * The source of a record whose entries live behind an adapter — a database, an
4389
+ * HTTP API, a bucket — instead of in the module.
4390
+ *
4391
+ * This is what `c.external()` returns, and it is the counterpart of the
4392
+ * `c.json(() => import(...))` marker a `.jsonValues()` entry carries: a value
4393
+ * that says "the content is not here" without saying anything about what is.
4394
+ * The schema says *which* adapter (`.external("posts")`); this says *that* the
4395
+ * entries are elsewhere, which is what every source-walking consumer needs to
4396
+ * know without holding a schema.
4397
+ *
4398
+ * Three phantom parameters, each earning its place:
4399
+ *
4400
+ * - `T` — the item type. Without it `c.define` would return a module whose type
4401
+ * is "a marker", the item type would be gone, and an adapter could not be
4402
+ * typed from the schema at all.
4403
+ * - `L` — the label from `.external(label)`, so a binding can be checked against
4404
+ * the schema that declared it.
4405
+ * - `RO` — whether the schema said `.readonly()`, which decides whether the
4406
+ * adapter must implement writes or is forbidden from doing so.
4407
+ *
4408
+ * The defaults are the WIDEST instantiation on purpose: the bare name appears in
4409
+ * the `Source` and `SelectorSource` unions, and every narrower instantiation has
4410
+ * to be assignable to it. The `external()` factory below defaults the other way,
4411
+ * exactly as `JsonSource<T = unknown>` and `json<T = Json>()` do.
4412
+ */
4413
+
4414
+ /**
4415
+ * The marker written as a module's source when its record is `.external()`.
4416
+ *
4417
+ * Takes no arguments: everything it carries is inferred from the schema it is
4418
+ * checked against in `c.define`. The assertion mirrors `json()` — the phantom
4419
+ * slots are symbol-keyed and have no runtime representation, so there is nothing
4420
+ * to construct for them.
4421
+ */
4422
+ function external() {
4423
+ return _defineProperty({}, VAL_EXTENSION, EXTERNAL_VAL_EXTENSION_TAG);
4424
+ }
4425
+ function isExternal(obj) {
4426
+ return _typeof(obj) === "object" && obj !== null && VAL_EXTENSION in obj && obj[VAL_EXTENSION] === EXTERNAL_VAL_EXTENSION_TAG;
4427
+ }
4428
+
4429
+ /**
4430
+ * The item type an external record holds, read back off a module.
4431
+ *
4432
+ * `GenericSelector` is not imported here — that would be a cycle through
4433
+ * `../selector` — so this is written against the phantom slot directly and the
4434
+ * selector-shaped overloads live where the selector types do.
4435
+ */
4436
+
4437
+ /** The label an external record was declared with. */
4438
+
4439
+ /** Whether the schema behind an external record said `.readonly()`. */
4440
+
4441
+ /**
4442
+ * The source of an external record as it may be WRITTEN.
4443
+ *
4444
+ * Either the marker, or entries inline in the `.val.ts`. Inline entries are
4445
+ * accepted by the type on purpose, for the same reason `.jsonValues()` accepts
4446
+ * them (see `JsonValuesRecordSrc`): pasting content straight into the module is
4447
+ * the natural first thing to write, and a type error there is a dead end — the
4448
+ * author cannot see what to write instead. Validation reports the inline entries
4449
+ * as an `external:upload` fix instead, so the mistake is repaired rather than
4450
+ * blocking authoring, and they are readable at runtime meanwhile.
4451
+ */
4452
+
4453
+ /**
4454
+ * Is this module source an external record that still has entries written
4455
+ * inline? Used by validation to raise `external:upload`.
4456
+ */
4457
+ function hasInlineExternalEntries(source) {
4458
+ return _typeof(source) === "object" && source !== null && !Array.isArray(source) && !isExternal(source) && Object.keys(source).length > 0;
4459
+ }
4460
+
4357
4461
  /**
4358
4462
  * The source type of a `.jsonValues()` record: every entry value is EITHER a
4359
4463
  * lazily loaded {@link JsonSource} whose resolved content is the (loosened, see
@@ -4382,6 +4486,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4382
4486
  var isJsonValues = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
4383
4487
  var previewInput = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : null;
4384
4488
  var renderInput = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : null;
4489
+ var externalLabel = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : null;
4385
4490
  _classCallCheck(this, RecordSchema);
4386
4491
  _this = _callSuper(this, RecordSchema);
4387
4492
  _this.item = item;
@@ -4396,24 +4501,28 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4396
4501
  _this.isJsonValues = isJsonValues;
4397
4502
  _this.previewInput = previewInput;
4398
4503
  _this.renderInput = renderInput;
4504
+ _this.externalLabel = externalLabel;
4399
4505
  return _this;
4400
4506
  }
4401
4507
  _inherits(RecordSchema, _Schema);
4402
4508
  return _createClass(RecordSchema, [{
4403
4509
  key: "describe",
4404
4510
  value: function describe(description) {
4405
- return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.isJsonValues, this.previewInput, this.renderInput);
4511
+ return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.isJsonValues, this.previewInput, this.renderInput, this.externalLabel);
4406
4512
  }
4407
4513
  }, {
4408
4514
  key: "validate",
4409
4515
  value: function validate(validationFunction) {
4410
- return new RecordSchema(this.item, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput);
4516
+ return new RecordSchema(this.item, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput, this.externalLabel);
4411
4517
  }
4412
4518
  }, {
4413
4519
  key: "executeValidate",
4414
4520
  value: function executeValidate(path, src) {
4415
4521
  var _this2 = this;
4416
4522
  var error = false;
4523
+ if (this.externalLabel !== null) {
4524
+ return this.validateExternal(path, src);
4525
+ }
4417
4526
  var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
4418
4527
  path: path
4419
4528
  });
@@ -4750,29 +4859,42 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4750
4859
  }, {
4751
4860
  key: "nullable",
4752
4861
  value: function nullable() {
4753
- return new RecordSchema(this.item, true, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput);
4862
+ return new RecordSchema(this.item, true, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput, this.externalLabel);
4754
4863
  }
4864
+
4865
+ /**
4866
+ * A record you can look at but not change.
4867
+ *
4868
+ * The flag rides in the TYPE as well as in the instance, so `.external()` can
4869
+ * freeze it into the source marker and the adapter's write methods become
4870
+ * required or forbidden on the strength of it. That is also why `.readonly()`
4871
+ * must come BEFORE `.external()`: afterwards the value is a `Schema`, and
4872
+ * there is no `.readonly()` left to call — which is the error the compiler
4873
+ * gives, and a clearer one than a runtime throw.
4874
+ */
4755
4875
  }, {
4756
4876
  key: "readonly",
4757
4877
  value: function readonly() {
4758
- return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, true, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput);
4878
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
4879
+ return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput, this.externalLabel);
4759
4880
  }
4760
4881
  }, {
4761
4882
  key: "hidden",
4762
4883
  value: function hidden() {
4763
- return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, true, this.description, this.isJsonValues, this.previewInput, this.renderInput);
4884
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
4885
+ return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput, this.externalLabel);
4764
4886
  }
4765
4887
  }, {
4766
4888
  key: "router",
4767
4889
  value: function router(_router) {
4768
- return new RecordSchema(this.item, this.opt, this.customValidateFunctions, _router, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput);
4890
+ return new RecordSchema(this.item, this.opt, this.customValidateFunctions, _router, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput, this.externalLabel);
4769
4891
  }
4770
4892
  }, {
4771
4893
  key: "remote",
4772
4894
  value: function remote() {
4773
4895
  return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions ? _objectSpread2(_objectSpread2({}, this.mediaOptions), {}, {
4774
4896
  remote: true
4775
- }) : undefined, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput);
4897
+ }) : undefined, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput, this.externalLabel);
4776
4898
  }
4777
4899
 
4778
4900
  /**
@@ -4814,7 +4936,84 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4814
4936
  // Empty by construction: the guard above rejects any that were registered.
4815
4937
  [], this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, true,
4816
4938
  // Null by construction: the guard above rejects any that was declared.
4817
- null, this.renderInput);
4939
+ null, this.renderInput, this.externalLabel);
4940
+ }
4941
+
4942
+ /**
4943
+ * Store this record's entries behind an adapter — a database, an HTTP API, a
4944
+ * bucket — instead of in the module.
4945
+ *
4946
+ * Available on every record-derived schema, which is `s.record()`,
4947
+ * `s.router()`, `s.images()` and `s.files()` alike: a router is a
4948
+ * `RecordSchema` with a `ValRouter`, a gallery one with media options, so all
4949
+ * four get external storage from this one method.
4950
+ *
4951
+ * `label` does not address the binding — the registry is keyed by module, and
4952
+ * so is the wire protocol. It exists so a reader of the schema can see what
4953
+ * backs it, and it is checked against the binding that claims it, so the two
4954
+ * cannot drift.
4955
+ *
4956
+ * Only supported on a module's ROOT record, exactly as `.jsonValues()` is: a
4957
+ * nested external record would leave a hole in the middle of a module's
4958
+ * source, and the Studio, patching and validation all assume a module's
4959
+ * source is complete apart from its entries.
4960
+ */
4961
+ }, {
4962
+ key: "external",
4963
+ value: function external(label) {
4964
+ if (this.isJsonValues) {
4965
+ throw new Error(".external() cannot be combined with .jsonValues(): entries live in one place or the other, not both.");
4966
+ }
4967
+ if (!label) {
4968
+ throw new Error('.external() requires a label, e.g. .external("posts")');
4969
+ }
4970
+ return new RecordSchema(this.item, this.opt,
4971
+ // Empty by construction: a validator declared before `.external()` is
4972
+ // typed against the un-external source shape and cannot be carried over.
4973
+ [], this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, null, this.renderInput, label);
4974
+ }
4975
+
4976
+ /**
4977
+ * An external record's source is either the `c.external()` marker or entries
4978
+ * still written inline in the `.val.ts`.
4979
+ *
4980
+ * Inline entries are NOT a type error (see `ExternalRecordWritableSrc`), so
4981
+ * this is where they surface: as an `external:upload` fix, per key, the way
4982
+ * `.jsonValues()` reports an un-extracted entry. Reporting per key rather than
4983
+ * once for the record is what lets the fix be applied to one entry, and what
4984
+ * puts the error at a path the editor can navigate to.
4985
+ */
4986
+ }, {
4987
+ key: "validateExternal",
4988
+ value: function validateExternal(path, src) {
4989
+ if (this.opt && (src === null || src === undefined)) {
4990
+ return false;
4991
+ }
4992
+ if (src === null || _typeof(src) !== "object" || Array.isArray(src)) {
4993
+ return _defineProperty({}, path, [{
4994
+ message: "Expected the c.external() marker or inline entries, got '".concat(src === null ? "null" : Array.isArray(src) ? "array" : _typeof(src), "'"),
4995
+ value: src,
4996
+ schemaError: true
4997
+ }]);
4998
+ }
4999
+ if (isExternal(src)) {
5000
+ // The marker: the entries are the adapter's, and there is nothing here to
5001
+ // check. Their content is validated as it is read.
5002
+ return false;
5003
+ }
5004
+ var error = false;
5005
+ for (var _i = 0, _Object$keys = Object.keys(src); _i < _Object$keys.length; _i++) {
5006
+ var _key = _Object$keys[_i];
5007
+ var subPath = createValPathOfItem(path, _key);
5008
+ if (!subPath) {
5009
+ continue;
5010
+ }
5011
+ error = this.appendValidationError(error, subPath, "Entry is written inline, but this record is .external(\"".concat(this.externalLabel, "\"). Run 'val external upload' to move it into the store."), src[_key]);
5012
+ var errors = error;
5013
+ var last = errors[subPath][errors[subPath].length - 1];
5014
+ last.fixes = ["external:upload"];
5015
+ }
5016
+ return error;
4818
5017
  }
4819
5018
  }, {
4820
5019
  key: "getRouterValidations",
@@ -4868,7 +5067,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4868
5067
  }, {
4869
5068
  key: "executeSerialize",
4870
5069
  value: function executeSerialize() {
4871
- var _this$renderInput, _this$keySchema, _this$currentRouter, _this$customValidateF;
5070
+ var _this$renderInput, _this$keySchema, _this$currentRouter, _this$customValidateF, _this$externalLabel;
4872
5071
  var result = {
4873
5072
  type: "record",
4874
5073
  render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
@@ -4879,6 +5078,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4879
5078
  router: (_this$currentRouter = this.currentRouter) === null || _this$currentRouter === void 0 ? void 0 : _this$currentRouter.getRouterId(),
4880
5079
  customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
4881
5080
  jsonValues: this.isJsonValues ? true : undefined,
5081
+ external: (_this$externalLabel = this.externalLabel) !== null && _this$externalLabel !== void 0 ? _this$externalLabel : undefined,
4882
5082
  readonly: this.isReadonly,
4883
5083
  hidden: this.isHidden,
4884
5084
  description: this.description
@@ -4916,8 +5116,12 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4916
5116
  if (src === null) {
4917
5117
  return res;
4918
5118
  }
4919
- for (var _key in src) {
4920
- var itemSrc = src[_key];
5119
+ if (isExternal(src)) {
5120
+ // The entries are the adapter's; there is nothing here to preview.
5121
+ return res;
5122
+ }
5123
+ for (var _key2 in src) {
5124
+ var itemSrc = src[_key2];
4921
5125
  if (itemSrc === null || itemSrc === undefined) {
4922
5126
  continue;
4923
5127
  }
@@ -4928,14 +5132,14 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4928
5132
  // keys, and the caller shows a placeholder for the rest.
4929
5133
  continue;
4930
5134
  }
4931
- var subPath = unsafeCreateSourcePath(sourcePath, _key);
5135
+ var subPath = unsafeCreateSourcePath(sourcePath, _key2);
4932
5136
  if (scope !== undefined && !scope.wantsUnder(subPath)) {
4933
5137
  continue;
4934
5138
  }
4935
5139
  var itemResult = this.item["executePreview"](subPath, itemSrc, scope);
4936
5140
  for (var keyS in itemResult) {
4937
- var _key2 = keyS;
4938
- res[_key2] = itemResult[_key2];
5141
+ var _key3 = keyS;
5142
+ res[_key3] = itemResult[_key3];
4939
5143
  }
4940
5144
  }
4941
5145
  // The entries preview comes from the ITEM schema's own `preview` — the
@@ -4946,9 +5150,9 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4946
5150
  // is being shown, only the wanted entries when it is not.
4947
5151
  var window = scope !== undefined && !scope.wants(sourcePath) ? scope : null;
4948
5152
  var items = [];
4949
- for (var _i = 0, _Object$entries = Object.entries(src); _i < _Object$entries.length; _i++) {
4950
- var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
4951
- _key3 = _Object$entries$_i[0],
5153
+ for (var _i2 = 0, _Object$entries = Object.entries(src); _i2 < _Object$entries.length; _i2++) {
5154
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i2], 2),
5155
+ _key4 = _Object$entries$_i[0],
4952
5156
  val = _Object$entries$_i[1];
4953
5157
  if (isJson(val)) {
4954
5158
  continue; // as above: nothing to select from an un-loaded entry
@@ -4956,7 +5160,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4956
5160
  if (val === null || val === undefined) {
4957
5161
  continue;
4958
5162
  }
4959
- if (window !== null && !window.wantsUnder(unsafeCreateSourcePath(sourcePath, _key3))) {
5163
+ if (window !== null && !window.wantsUnder(unsafeCreateSourcePath(sourcePath, _key4))) {
4960
5164
  continue;
4961
5165
  }
4962
5166
  // Per KEY, not per record: the closure is user code, and one entry whose
@@ -4968,14 +5172,14 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
4968
5172
  var title = _item.title,
4969
5173
  subtitle = _item.subtitle,
4970
5174
  image = _item.image;
4971
- items.push([_key3, {
5175
+ items.push([_key4, {
4972
5176
  title: title,
4973
5177
  subtitle: subtitle,
4974
5178
  image: image
4975
5179
  }]);
4976
5180
  }
4977
5181
  } catch (e) {
4978
- res[unsafeCreateSourcePath(sourcePath, _key3)] = {
5182
+ res[unsafeCreateSourcePath(sourcePath, _key4)] = {
4979
5183
  status: "error",
4980
5184
  message: e instanceof Error ? e.message : "Unknown error"
4981
5185
  };
@@ -5016,7 +5220,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5016
5220
  }, {
5017
5221
  key: "preview",
5018
5222
  value: function preview(select) {
5019
- return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, select, this.renderInput);
5223
+ return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, select, this.renderInput, this.externalLabel);
5020
5224
  }
5021
5225
 
5022
5226
  /**
@@ -5029,7 +5233,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
5029
5233
  }, {
5030
5234
  key: "render",
5031
5235
  value: function render(input) {
5032
- return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, input);
5236
+ return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, input, this.externalLabel);
5033
5237
  }
5034
5238
  }]);
5035
5239
  }(Schema);
@@ -5049,135 +5253,653 @@ function record(keyOrSchema, schema) {
5049
5253
  }
5050
5254
  }
5051
5255
 
5052
- function define(id,
5053
- // TODO: `/${string}`
5054
- schema, source) {
5055
- return _defineProperty(_defineProperty(_defineProperty({}, GetSource, source), GetSchema, schema), Path, id);
5056
- }
5057
- function getSource(valModule) {
5058
- return valModule[GetSource];
5059
- }
5256
+ /**
5257
+ * The source of the project's settings module — `s.settings()`.
5258
+ *
5259
+ * **Every key is optional, at every level, and that is the whole point.** A
5260
+ * settings module is written as
5261
+ *
5262
+ * ```typescript
5263
+ * export default c.define("/settings.val.ts", s.settings(), {});
5264
+ * ```
5265
+ *
5266
+ * and `{}` has to keep validating as sections are added to it. A project that
5267
+ * never touched the assistant's settings should not have to edit its settings
5268
+ * file the day `locales` or `permissions` land.
5269
+ *
5270
+ * That is why settings is not sugar over `s.object()`: an object schema errors
5271
+ * with `Expected key 'assistant' not found in object` for any absent key (see
5272
+ * `ObjectSchema.executeAssert`), and `.nullable()` permits `null`, not absence.
5273
+ * `SettingsSchema` gives absent keys the meaning "unset" instead.
5274
+ *
5275
+ * `null` means unset too, so the editor can clear a field it has already
5276
+ * written without removing the key.
5277
+ */
5060
5278
 
5061
5279
  /**
5062
- * Whether `value` is a Val module, i.e. something {@link define} produced.
5280
+ * The assistant: whether editors have one, and what it is told about the
5281
+ * project on every message.
5063
5282
  *
5064
- * Checks for the three symbols `define` writes, rather than a class identity:
5065
- * a module may have been created by a different copy of `@valbuild/core` (the
5066
- * editor SPA and the host bundle each ship their own, and the CLI evaluates
5067
- * user modules inside a `node:vm` context). The symbols are created with
5068
- * `Symbol.for`, so they are shared across all of those; a constructor is not.
5283
+ * `context` and `tone` are prose the model reads, not instructions Val
5284
+ * interprets, and both are capped (see {@link ASSISTANT_SETTINGS_MAX_LENGTH}):
5285
+ * they are prepended to every request the chat makes, so an unbounded field
5286
+ * here is an unbounded cost on every turn.
5069
5287
  */
5070
- function isValModule(value) {
5071
- return _typeof(value) === "object" && value !== null && GetSource in value && GetSchema in value && Path in value;
5072
- }
5073
- function splitModuleFilePathAndModulePath(path) {
5074
- var pathOfSep = path.indexOf(ModuleFilePathSep);
5075
- if (pathOfSep === -1) {
5076
- return [path, ""];
5077
- }
5078
- return [path.slice(0, pathOfSep), path.slice(pathOfSep + ModuleFilePathSep.length)];
5079
- }
5080
- function joinModuleFilePathAndModulePath(moduleFilePath, modulePath) {
5081
- if (modulePath === "") {
5082
- return moduleFilePath;
5083
- }
5084
- return "".concat(moduleFilePath).concat(ModuleFilePathSep).concat(modulePath);
5085
- }
5086
- function isObjectSchema(schema) {
5087
- return schema instanceof ObjectSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "object";
5088
- }
5089
- function isRecordSchema(schema) {
5090
- return schema instanceof RecordSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "record";
5091
- }
5092
- function isArraySchema(schema) {
5093
- return schema instanceof ArraySchema || _typeof(schema) === "object" && "type" in schema && schema.type === "array";
5094
- }
5095
5288
 
5096
- // function isI18nSchema(
5097
- // schema: Schema<SelectorSource> | SerializedSchema
5098
- // ): schema is I18nSchema<readonly string[]> | SerializedI18nSchema {
5099
- // return (
5100
- // schema instanceof I18nSchema ||
5101
- // (typeof schema === "object" && "type" in schema && schema.type === "i18n")
5102
- // );
5103
- // }
5289
+ /**
5290
+ * The cap on each of the assistant's prose fields, in characters.
5291
+ *
5292
+ * Roughly a thousand tokens each. Generous enough for a paragraph of
5293
+ * background and a house style, small enough that the two of them together do
5294
+ * not dominate the system prompt they are appended to.
5295
+ */
5296
+ var ASSISTANT_SETTINGS_MAX_LENGTH = 4000;
5104
5297
 
5105
- function isUnionSchema(schema
5106
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5107
- ) {
5108
- return schema instanceof UnionSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "union";
5109
- }
5110
- function isRichTextSchema(schema) {
5111
- return schema instanceof RichTextSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "richtext";
5112
- }
5113
- function isImageSchema(schema) {
5114
- return schema instanceof ImageSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "image";
5115
- }
5298
+ /**
5299
+ * Whether a project has an assistant — and the answer is not a boolean.
5300
+ *
5301
+ * - `"on"`: use it.
5302
+ * - `"off"`: every trace of it goes. No button in the top bar, no row in the
5303
+ * quick actions, no panel, nothing sent. A project that says `false` has
5304
+ * decided, and the Studio does not keep offering.
5305
+ * - `"unconfigured"`: nobody has said. The affordances are SHOWN, and asking to
5306
+ * use the assistant asks to turn it on first. That is the difference between
5307
+ * this and `"off"`, and the reason `enabled` is a tri-state: hiding an
5308
+ * unconfigured assistant means nobody discovers it, and quietly enabling one
5309
+ * means a project starts sending its content to a model because it did not
5310
+ * know to say no.
5311
+ *
5312
+ * A project with NO settings module is `"on"`. There is nowhere to record a
5313
+ * decision, so there is nothing to prompt for and nothing to prompt INTO — the
5314
+ * prompt writes to a settings module, and that project has none.
5315
+ *
5316
+ * This is the only answer to "does this project have an assistant":
5317
+ * `config.ai.chat` is gone, and with it the chat's title, description and
5318
+ * suggestions, which nothing replaces. The AI commit-message summariser is
5319
+ * deliberately not part of this — `config.ai.commitMessages` stays where it is,
5320
+ * and gets settings of its own later.
5321
+ */
5116
5322
 
5117
- // function isOneOfSchema(
5118
- // schema: Schema<SelectorSource> | SerializedSchema
5119
- // ): schema is OneOfSchema<GenericSelector<SourceArray>> | SerializedOneOfSchema {
5120
- // return (
5121
- // schema instanceof OneOfSchema ||
5122
- // (typeof schema === "object" && "type" in schema && schema.type === "oneOf")
5123
- // );
5124
- // }
5323
+ function assistantAvailability(/** The settings module's source, or `undefined` where the project has none. */
5324
+ settings) {
5325
+ var _settings$assistant;
5326
+ if (settings === undefined) {
5327
+ return "on";
5328
+ }
5329
+ var enabled = (_settings$assistant = settings.assistant) === null || _settings$assistant === void 0 ? void 0 : _settings$assistant.enabled;
5330
+ if (enabled === true) {
5331
+ return "on";
5332
+ }
5333
+ if (enabled === false) {
5334
+ return "off";
5335
+ }
5336
+ return "unconfigured";
5337
+ }
5125
5338
 
5126
- function resolvePath(path, valModule, schema) {
5127
- var parts = splitModulePath(path);
5128
- var origParts = _toConsumableArray(parts);
5129
- var resolvedSchema = schema;
5130
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5131
- var resolvedSource = valModule;
5132
- var _loop = function _loop() {
5133
- var part = parts.shift();
5134
- if (part === undefined) {
5135
- throw Error("Unexpected undefined part");
5339
+ var BooleanSchema = /*#__PURE__*/function (_Schema) {
5340
+ function BooleanSchema() {
5341
+ var _this;
5342
+ var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
5343
+ var customValidateFunctions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
5344
+ var isReadonly = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
5345
+ var isHidden = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
5346
+ var description = arguments.length > 4 ? arguments[4] : undefined;
5347
+ var renderInput = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;
5348
+ var previewInput = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
5349
+ _classCallCheck(this, BooleanSchema);
5350
+ _this = _callSuper(this, BooleanSchema);
5351
+ _this.opt = opt;
5352
+ _this.customValidateFunctions = customValidateFunctions;
5353
+ _this.isReadonly = isReadonly;
5354
+ _this.isHidden = isHidden;
5355
+ _this.description = description;
5356
+ _this.renderInput = renderInput;
5357
+ _this.previewInput = previewInput;
5358
+ return _this;
5359
+ }
5360
+ _inherits(BooleanSchema, _Schema);
5361
+ return _createClass(BooleanSchema, [{
5362
+ key: "describe",
5363
+ value: function describe(description) {
5364
+ return new BooleanSchema(this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
5365
+ }
5366
+ }, {
5367
+ key: "validate",
5368
+ value: function validate(validationFunction) {
5369
+ return new BooleanSchema(this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
5370
+ }
5371
+ }, {
5372
+ key: "executeValidate",
5373
+ value: function executeValidate(path, src) {
5374
+ if (this.opt && (src === null || src === undefined)) {
5375
+ return false;
5136
5376
  }
5137
- if (isArraySchema(resolvedSchema)) {
5138
- var _resolvedSchema;
5139
- if (Number.isNaN(Number(part))) {
5140
- throw Error("Invalid path: array schema ".concat(JSON.stringify(resolvedSchema), " must have a number as path, but got ").concat(part, ". Path: ").concat(path));
5141
- }
5142
- if (_typeof(resolvedSource) !== "object" && !Array.isArray(resolvedSource)) {
5143
- throw Error("Schema type error: expected source to be type of array, but got ".concat(_typeof(resolvedSource)));
5144
- }
5145
- resolvedSource = resolvedSource[part];
5146
- resolvedSchema = resolvedSchema instanceof ArraySchema ? (_resolvedSchema = resolvedSchema) === null || _resolvedSchema === void 0 ? void 0 : _resolvedSchema["item"] : resolvedSchema.item;
5147
- } else if (isRecordSchema(resolvedSchema)) {
5148
- var _resolvedSchema2;
5149
- if (typeof part !== "string") {
5150
- throw Error("Invalid path: record schema ".concat(resolvedSchema, " must have path: ").concat(part, " as string"));
5151
- }
5152
- if (_typeof(resolvedSource) !== "object" && !Array.isArray(resolvedSource)) {
5153
- throw Error("Schema type error: expected source to be type of record, but got ".concat(_typeof(resolvedSource)));
5154
- }
5155
- if (!resolvedSource[part]) {
5156
- throw Error("Invalid path: record source did not have key ".concat(part, " from path: ").concat(path));
5157
- }
5158
- resolvedSource = resolvedSource[part];
5159
- resolvedSchema = resolvedSchema instanceof RecordSchema ? (_resolvedSchema2 = resolvedSchema) === null || _resolvedSchema2 === void 0 ? void 0 : _resolvedSchema2["item"] : resolvedSchema.item;
5160
- // A `.jsonValues()` entry value is a lazily-loaded JsonSource marker. We
5161
- // can resolve the entry itself (schema is now `item`), but we cannot
5162
- // descend deeper until the backing `*.val.json` content has been loaded
5163
- // and substituted into the source tree (done by the UI/server layer).
5164
- if (isJson(resolvedSource) && parts.length > 0) {
5165
- throw Error("Cannot resolve path into a jsonValues entry until its content is loaded. Path: ".concat(path));
5166
- }
5167
- } else if (isObjectSchema(resolvedSchema)) {
5168
- if (_typeof(resolvedSource) !== "object") {
5169
- throw Error("Schema type error: expected source to be type of object, but got ".concat(_typeof(resolvedSource)));
5170
- }
5171
- if (resolvedSource !== null && resolvedSource[part] === undefined) {
5172
- throw Error("Invalid path: object source did not have key ".concat(part, " from path: ").concat(path));
5173
- }
5174
- resolvedSource = resolvedSource === null ? resolvedSource : resolvedSource[part];
5175
- resolvedSchema = resolvedSchema instanceof ObjectSchema ? resolvedSchema["items"][part] : resolvedSchema.items[part];
5176
- // } else if (isI18nSchema(resolvedSchema)) {
5177
- // if (!resolvedSchema.locales.includes(part)) {
5178
- // throw Error(
5179
- // `Invalid path: i18n schema ${resolvedSchema} supports locales ${resolvedSchema.locales.join(
5180
- // ", "
5377
+ if (typeof src !== "boolean") {
5378
+ return _defineProperty({}, path, [{
5379
+ message: "Expected 'boolean', got '".concat(_typeof(src), "'"),
5380
+ value: src
5381
+ }]);
5382
+ }
5383
+ return false;
5384
+ }
5385
+ }, {
5386
+ key: "executeAssert",
5387
+ value: function executeAssert(path, src) {
5388
+ if (this.opt && src === null) {
5389
+ return {
5390
+ success: true,
5391
+ data: src
5392
+ };
5393
+ }
5394
+ if (src === null) {
5395
+ return {
5396
+ success: false,
5397
+ errors: _defineProperty({}, path, [{
5398
+ message: "Expected 'boolean', got 'null'",
5399
+ typeError: true
5400
+ }])
5401
+ };
5402
+ }
5403
+ if (typeof src !== "boolean") {
5404
+ return {
5405
+ success: false,
5406
+ errors: _defineProperty({}, path, [{
5407
+ message: "Expected 'boolean', got '".concat(_typeof(src), "'"),
5408
+ typeError: true
5409
+ }])
5410
+ };
5411
+ }
5412
+ return {
5413
+ success: true,
5414
+ data: src
5415
+ };
5416
+ }
5417
+ }, {
5418
+ key: "nullable",
5419
+ value: function nullable() {
5420
+ return new BooleanSchema(true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
5421
+ }
5422
+ }, {
5423
+ key: "readonly",
5424
+ value: function readonly() {
5425
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
5426
+ return new BooleanSchema(this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
5427
+ }
5428
+ }, {
5429
+ key: "hidden",
5430
+ value: function hidden() {
5431
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
5432
+ return new BooleanSchema(this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
5433
+ }
5434
+ }, {
5435
+ key: "executeCustomValidateAt",
5436
+ value: function executeCustomValidateAt(path, src) {
5437
+ return this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
5438
+ path: path
5439
+ });
5440
+ }
5441
+
5442
+ /**
5443
+ * How this field is laid out in the editor when it is the item of an array
5444
+ * or record: `{ as: "inline" }` renders the field itself inside each row,
5445
+ * instead of a preview row that navigates to it.
5446
+ *
5447
+ * Static configuration, not a callback — see `render.ts`.
5448
+ */
5449
+ }, {
5450
+ key: "render",
5451
+ value: function render(input) {
5452
+ return new BooleanSchema(this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, input, this.previewInput);
5453
+ }
5454
+
5455
+ /**
5456
+ * How this VALUE is shown where a preview of it is needed — a row in a
5457
+ * sortable list, a reference dropdown, a search hit. Never how the field
5458
+ * itself is edited (that is `render`). See `preview.ts`.
5459
+ */
5460
+ }, {
5461
+ key: "preview",
5462
+ value: function preview(select) {
5463
+ return new BooleanSchema(this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, select);
5464
+ }
5465
+ }, {
5466
+ key: "executePreviewItem",
5467
+ value: function executePreviewItem(src) {
5468
+ if (this.previewInput === null) {
5469
+ return null;
5470
+ }
5471
+ return this.previewInput({
5472
+ val: src
5473
+ });
5474
+ }
5475
+ }, {
5476
+ key: "declaresItemPreview",
5477
+ value: function declaresItemPreview() {
5478
+ return this.previewInput !== null;
5479
+ }
5480
+ }, {
5481
+ key: "executeSerialize",
5482
+ value: function executeSerialize() {
5483
+ var _this$renderInput, _this$customValidateF;
5484
+ return {
5485
+ type: "boolean",
5486
+ render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
5487
+ preview: this.previewInput ? true : undefined,
5488
+ opt: this.opt,
5489
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
5490
+ readonly: this.isReadonly,
5491
+ hidden: this.isHidden,
5492
+ description: this.description
5493
+ };
5494
+ }
5495
+ }, {
5496
+ key: "executePreview",
5497
+ value: function executePreview() {
5498
+ return {};
5499
+ }
5500
+ }]);
5501
+ }(Schema);
5502
+ var _boolean = function _boolean() {
5503
+ return new BooleanSchema();
5504
+ };
5505
+
5506
+ /**
5507
+ * An object whose keys are all optional: absent means unset.
5508
+ *
5509
+ * Both the settings module itself and each of its sections are this. See
5510
+ * {@link SettingsSource} for why settings cannot be an object schema, and
5511
+ * {@link settings} for what a settings module holds.
5512
+ *
5513
+ * There is no `describe`, `validate`, `render` or `preview` on purpose: the
5514
+ * shape is Val's, not the schema author's — `s.settings()` takes no arguments —
5515
+ * and the Studio renders each section with a UI built for it.
5516
+ */
5517
+ var SettingsSchema = /*#__PURE__*/function (_Schema) {
5518
+ function SettingsSchema(items) {
5519
+ var _this;
5520
+ var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
5521
+ var isReadonly = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
5522
+ var isHidden = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
5523
+ var description = arguments.length > 4 ? arguments[4] : undefined;
5524
+ _classCallCheck(this, SettingsSchema);
5525
+ _this = _callSuper(this, SettingsSchema);
5526
+ _this.items = items;
5527
+ _this.opt = opt;
5528
+ _this.isReadonly = isReadonly;
5529
+ _this.isHidden = isHidden;
5530
+ _this.description = description;
5531
+ return _this;
5532
+ }
5533
+ _inherits(SettingsSchema, _Schema);
5534
+ return _createClass(SettingsSchema, [{
5535
+ key: "executeValidate",
5536
+ value: function executeValidate(path, src) {
5537
+ var error = false;
5538
+ if (src === null || src === undefined) {
5539
+ if (this.opt) {
5540
+ return false;
5541
+ }
5542
+ return _defineProperty({}, path, [{
5543
+ message: "Expected 'object', got '".concat(src, "'")
5544
+ }]);
5545
+ }
5546
+ if (_typeof(src) !== "object") {
5547
+ return _defineProperty({}, path, [{
5548
+ message: "Expected 'object', got '".concat(_typeof(src), "'")
5549
+ }]);
5550
+ }
5551
+ if (Array.isArray(src)) {
5552
+ return _defineProperty({}, path, [{
5553
+ message: "Expected 'object', got 'array'"
5554
+ }]);
5555
+ }
5556
+ for (var _i = 0, _Object$entries = Object.entries(this.items); _i < _Object$entries.length; _i++) {
5557
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
5558
+ _key = _Object$entries$_i[0],
5559
+ schema = _Object$entries$_i[1];
5560
+ // Absent is the unset value, so there is nothing to validate. A key that
5561
+ // is present as `undefined` is the same statement written differently.
5562
+ if (src[_key] === undefined) {
5563
+ continue;
5564
+ }
5565
+ var subPath = createValPathOfItem(path, _key);
5566
+ if (!subPath) {
5567
+ error = this.appendValidationError(error, path, "Internal error: could not create path at ".concat(!path && typeof path === "string" ? "<empty string>" : path, " at key ").concat(_key),
5568
+ // Should! never happen
5569
+ src);
5570
+ } else {
5571
+ var subError = schema["executeValidate"](subPath, src[_key]);
5572
+ error = this.mergeValidationErrors(error, subError);
5573
+ }
5574
+ }
5575
+ // An unknown key is reported rather than ignored (which is what an object
5576
+ // schema does with extra keys): the shape is closed and Val-defined, so the
5577
+ // realistic cause is a typo — `toneOfVoice` for `tone` — and silence there
5578
+ // means a setting that never takes effect and never says why.
5579
+ for (var _i2 = 0, _Object$keys = Object.keys(src); _i2 < _Object$keys.length; _i2++) {
5580
+ var _key2 = _Object$keys[_i2];
5581
+ if (!(_key2 in this.items)) {
5582
+ error = this.appendValidationError(error, path, "Unknown settings key: '".concat(_key2, "'. Expected one of: ").concat(Object.keys(this.items).map(function (key) {
5583
+ return "'".concat(key, "'");
5584
+ }).join(", ")), src, true);
5585
+ }
5586
+ }
5587
+ return error;
5588
+ }
5589
+ }, {
5590
+ key: "executeAssert",
5591
+ value: function executeAssert(path, src) {
5592
+ if (this.opt && src === null) {
5593
+ return {
5594
+ success: true,
5595
+ data: src
5596
+ };
5597
+ }
5598
+ var typeError = function typeError(got) {
5599
+ return {
5600
+ message: "Expected 'object', got '".concat(got, "'"),
5601
+ typeError: true
5602
+ };
5603
+ };
5604
+ if (src === null) {
5605
+ return {
5606
+ success: false,
5607
+ errors: _defineProperty({}, path, [typeError("null")])
5608
+ };
5609
+ }
5610
+ if (_typeof(src) !== "object") {
5611
+ return {
5612
+ success: false,
5613
+ errors: _defineProperty({}, path, [typeError(_typeof(src))])
5614
+ };
5615
+ }
5616
+ if (Array.isArray(src)) {
5617
+ return {
5618
+ success: false,
5619
+ errors: _defineProperty({}, path, [typeError("array")])
5620
+ };
5621
+ }
5622
+ // No per-key check, unlike an object schema: every key is optional, so an
5623
+ // object is all this can assert.
5624
+ return {
5625
+ success: true,
5626
+ data: src
5627
+ };
5628
+ }
5629
+ }, {
5630
+ key: "nullable",
5631
+ value: function nullable() {
5632
+ return new SettingsSchema(this.items, true, this.isReadonly, this.isHidden, this.description);
5633
+ }
5634
+ }, {
5635
+ key: "readonly",
5636
+ value: function readonly() {
5637
+ return new SettingsSchema(this.items, this.opt, true, this.isHidden, this.description);
5638
+ }
5639
+ }, {
5640
+ key: "hidden",
5641
+ value: function hidden() {
5642
+ return new SettingsSchema(this.items, this.opt, this.isReadonly, true, this.description);
5643
+ }
5644
+ }, {
5645
+ key: "executeCustomValidateAt",
5646
+ value: function executeCustomValidateAt() {
5647
+ // Settings declares no `validate`, so there are no custom validators to
5648
+ // run. Implemented rather than inherited because the base class makes this
5649
+ // abstract on purpose — see `Schema.executeCustomValidateAt`.
5650
+ return [];
5651
+ }
5652
+ }, {
5653
+ key: "executeSerialize",
5654
+ value: function executeSerialize() {
5655
+ return {
5656
+ type: "settings",
5657
+ items: Object.fromEntries(Object.entries(this.items).map(function (_ref4) {
5658
+ var _ref5 = _slicedToArray(_ref4, 2),
5659
+ key = _ref5[0],
5660
+ schema = _ref5[1];
5661
+ return [key, schema["executeSerialize"]()];
5662
+ })),
5663
+ opt: this.opt,
5664
+ readonly: this.isReadonly,
5665
+ hidden: this.isHidden,
5666
+ description: this.description
5667
+ };
5668
+ }
5669
+ }, {
5670
+ key: "executePreview",
5671
+ value: function executePreview(sourcePath, src, scope) {
5672
+ var res = {};
5673
+ if (src === null) {
5674
+ return res;
5675
+ }
5676
+ for (var _key3 in this.items) {
5677
+ var itemSrc = src[_key3];
5678
+ if (itemSrc === null || itemSrc === undefined) {
5679
+ continue;
5680
+ }
5681
+ var subPath = unsafeCreateSourcePath(sourcePath, _key3);
5682
+ if (scope !== undefined && !scope.wantsUnder(subPath)) {
5683
+ continue;
5684
+ }
5685
+ var itemResult = this.items[_key3]["executePreview"](subPath, itemSrc, scope);
5686
+ for (var keyS in itemResult) {
5687
+ var _key4 = keyS;
5688
+ res[_key4] = itemResult[_key4];
5689
+ }
5690
+ }
5691
+ return res;
5692
+ }
5693
+ }]);
5694
+ }(Schema);
5695
+
5696
+ /**
5697
+ * Define the project's settings.
5698
+ *
5699
+ * One settings module per project, at the root of the content tree — a module
5700
+ * file path with no directory segment, `/settings.val.ts` by convention:
5701
+ *
5702
+ * ```typescript
5703
+ * export default c.define("/settings.val.ts", s.settings(), {});
5704
+ * ```
5705
+ *
5706
+ * Every section is optional, so `{}` is a complete settings module and stays
5707
+ * one as sections are added. Fill in what the project needs:
5708
+ *
5709
+ * ```typescript
5710
+ * export default c.define("/settings.val.ts", s.settings(), {
5711
+ * assistant: {
5712
+ * enabled: true,
5713
+ * context: "Val is a CMS for developers. British English, and 'Val' is never 'VAL'.",
5714
+ * tone: "Plain and direct. No exclamation marks, sentence case in headings.",
5715
+ * },
5716
+ * });
5717
+ * ```
5718
+ *
5719
+ * The Studio edits it under the cog at the foot of the left rail, and the
5720
+ * assistant is told `assistant.context` and `assistant.tone` on every message.
5721
+ *
5722
+ * `s.settings()` takes no arguments: the shape is Val's, which is what lets the
5723
+ * Studio render a UI built for each field rather than a generic form. A
5724
+ * project's own global content — a site name, social links — belongs in a
5725
+ * module of its own.
5726
+ */
5727
+ function settings() {
5728
+ return new SettingsSchema({
5729
+ assistant: new SettingsSchema({
5730
+ 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."),
5731
+ 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."),
5732
+ 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.")
5733
+ })
5734
+ });
5735
+ }
5736
+
5737
+ /**
5738
+ * What may be WRITTEN as an external record's source, on top of the marker.
5739
+ *
5740
+ * Entries inline in the `.val.ts` are accepted on purpose — the same call
5741
+ * `.jsonValues()` makes for the same reason: pasting content straight into the
5742
+ * module is the natural first thing to write, and a type error there is a dead
5743
+ * end, because the author cannot see what to write instead. Validation reports
5744
+ * them as an `external:upload` fix, and they are readable at runtime meanwhile.
5745
+ *
5746
+ * Widened HERE rather than in the schema's own source type so that the MODULE
5747
+ * stays typed on the marker alone. An adapter is bound to a module, and a module
5748
+ * whose type were "marker or plain record" would be indistinguishable from an
5749
+ * ordinary record — which would let `entry()` accept a module that is not
5750
+ * external at all.
5751
+ */
5752
+
5753
+ function define(id,
5754
+ // TODO: `/${string}`
5755
+ schema, source) {
5756
+ return _defineProperty(_defineProperty(_defineProperty({}, GetSource, source), GetSchema, schema), Path, id);
5757
+ }
5758
+ function getSource(valModule) {
5759
+ return valModule[GetSource];
5760
+ }
5761
+
5762
+ /**
5763
+ * Whether `value` is a Val module, i.e. something {@link define} produced.
5764
+ *
5765
+ * Checks for the three symbols `define` writes, rather than a class identity:
5766
+ * a module may have been created by a different copy of `@valbuild/core` (the
5767
+ * editor SPA and the host bundle each ship their own, and the CLI evaluates
5768
+ * user modules inside a `node:vm` context). The symbols are created with
5769
+ * `Symbol.for`, so they are shared across all of those; a constructor is not.
5770
+ */
5771
+ function isValModule(value) {
5772
+ return _typeof(value) === "object" && value !== null && GetSource in value && GetSchema in value && Path in value;
5773
+ }
5774
+ function splitModuleFilePathAndModulePath(path) {
5775
+ var pathOfSep = path.indexOf(ModuleFilePathSep);
5776
+ if (pathOfSep === -1) {
5777
+ return [path, ""];
5778
+ }
5779
+ return [path.slice(0, pathOfSep), path.slice(pathOfSep + ModuleFilePathSep.length)];
5780
+ }
5781
+ function joinModuleFilePathAndModulePath(moduleFilePath, modulePath) {
5782
+ if (modulePath === "") {
5783
+ return moduleFilePath;
5784
+ }
5785
+ return "".concat(moduleFilePath).concat(ModuleFilePathSep).concat(modulePath);
5786
+ }
5787
+ function isObjectSchema(schema) {
5788
+ return schema instanceof ObjectSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "object";
5789
+ }
5790
+
5791
+ /**
5792
+ * Settings, which walks like an object but whose keys are all OPTIONAL.
5793
+ *
5794
+ * That difference is the whole reason it is not an object schema: descending
5795
+ * into an unset section must resolve to `undefined`, not fail — see
5796
+ * `SettingsSource`.
5797
+ */
5798
+ function isSettingsSchema(schema) {
5799
+ return schema instanceof SettingsSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "settings";
5800
+ }
5801
+ function isRecordSchema(schema) {
5802
+ return schema instanceof RecordSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "record";
5803
+ }
5804
+ function isArraySchema(schema) {
5805
+ return schema instanceof ArraySchema || _typeof(schema) === "object" && "type" in schema && schema.type === "array";
5806
+ }
5807
+
5808
+ // function isI18nSchema(
5809
+ // schema: Schema<SelectorSource> | SerializedSchema
5810
+ // ): schema is I18nSchema<readonly string[]> | SerializedI18nSchema {
5811
+ // return (
5812
+ // schema instanceof I18nSchema ||
5813
+ // (typeof schema === "object" && "type" in schema && schema.type === "i18n")
5814
+ // );
5815
+ // }
5816
+
5817
+ function isUnionSchema(schema
5818
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5819
+ ) {
5820
+ return schema instanceof UnionSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "union";
5821
+ }
5822
+ function isRichTextSchema(schema) {
5823
+ return schema instanceof RichTextSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "richtext";
5824
+ }
5825
+ function isImageSchema(schema) {
5826
+ return schema instanceof ImageSchema || _typeof(schema) === "object" && "type" in schema && schema.type === "image";
5827
+ }
5828
+
5829
+ // function isOneOfSchema(
5830
+ // schema: Schema<SelectorSource> | SerializedSchema
5831
+ // ): schema is OneOfSchema<GenericSelector<SourceArray>> | SerializedOneOfSchema {
5832
+ // return (
5833
+ // schema instanceof OneOfSchema ||
5834
+ // (typeof schema === "object" && "type" in schema && schema.type === "oneOf")
5835
+ // );
5836
+ // }
5837
+
5838
+ function resolvePath(path, valModule, schema) {
5839
+ var parts = splitModulePath(path);
5840
+ var origParts = _toConsumableArray(parts);
5841
+ var resolvedSchema = schema;
5842
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5843
+ var resolvedSource = valModule;
5844
+ var _loop = function _loop() {
5845
+ var part = parts.shift();
5846
+ if (part === undefined) {
5847
+ throw Error("Unexpected undefined part");
5848
+ }
5849
+ if (isArraySchema(resolvedSchema)) {
5850
+ var _resolvedSchema;
5851
+ if (Number.isNaN(Number(part))) {
5852
+ throw Error("Invalid path: array schema ".concat(JSON.stringify(resolvedSchema), " must have a number as path, but got ").concat(part, ". Path: ").concat(path));
5853
+ }
5854
+ if (_typeof(resolvedSource) !== "object" && !Array.isArray(resolvedSource)) {
5855
+ throw Error("Schema type error: expected source to be type of array, but got ".concat(_typeof(resolvedSource)));
5856
+ }
5857
+ resolvedSource = resolvedSource[part];
5858
+ resolvedSchema = resolvedSchema instanceof ArraySchema ? (_resolvedSchema = resolvedSchema) === null || _resolvedSchema === void 0 ? void 0 : _resolvedSchema["item"] : resolvedSchema.item;
5859
+ } else if (isRecordSchema(resolvedSchema)) {
5860
+ var _resolvedSchema2;
5861
+ if (typeof part !== "string") {
5862
+ throw Error("Invalid path: record schema ".concat(resolvedSchema, " must have path: ").concat(part, " as string"));
5863
+ }
5864
+ if (_typeof(resolvedSource) !== "object" && !Array.isArray(resolvedSource)) {
5865
+ throw Error("Schema type error: expected source to be type of record, but got ".concat(_typeof(resolvedSource)));
5866
+ }
5867
+ if (!resolvedSource[part]) {
5868
+ throw Error("Invalid path: record source did not have key ".concat(part, " from path: ").concat(path));
5869
+ }
5870
+ resolvedSource = resolvedSource[part];
5871
+ resolvedSchema = resolvedSchema instanceof RecordSchema ? (_resolvedSchema2 = resolvedSchema) === null || _resolvedSchema2 === void 0 ? void 0 : _resolvedSchema2["item"] : resolvedSchema.item;
5872
+ // A `.jsonValues()` entry value is a lazily-loaded JsonSource marker. We
5873
+ // can resolve the entry itself (schema is now `item`), but we cannot
5874
+ // descend deeper until the backing `*.val.json` content has been loaded
5875
+ // and substituted into the source tree (done by the UI/server layer).
5876
+ if (isJson(resolvedSource) && parts.length > 0) {
5877
+ throw Error("Cannot resolve path into a jsonValues entry until its content is loaded. Path: ".concat(path));
5878
+ }
5879
+ } else if (isSettingsSchema(resolvedSchema)) {
5880
+ if (resolvedSource !== null && resolvedSource !== undefined && _typeof(resolvedSource) !== "object") {
5881
+ throw Error("Schema type error: expected source to be type of object, but got ".concat(_typeof(resolvedSource)));
5882
+ }
5883
+ // An absent key is NOT an error here, unlike an object's: every settings
5884
+ // key is optional, so a path into a section the project has not set
5885
+ // resolves to `undefined` — and keeps resolving, one level per part, so a
5886
+ // path two deep into an unset section still lands on the right schema.
5887
+ resolvedSource = resolvedSource === null || resolvedSource === undefined ? resolvedSource : resolvedSource[part];
5888
+ resolvedSchema = resolvedSchema instanceof SettingsSchema ? resolvedSchema["items"][part] : resolvedSchema.items[part];
5889
+ } else if (isObjectSchema(resolvedSchema)) {
5890
+ if (_typeof(resolvedSource) !== "object") {
5891
+ throw Error("Schema type error: expected source to be type of object, but got ".concat(_typeof(resolvedSource)));
5892
+ }
5893
+ if (resolvedSource !== null && resolvedSource[part] === undefined) {
5894
+ throw Error("Invalid path: object source did not have key ".concat(part, " from path: ").concat(path));
5895
+ }
5896
+ resolvedSource = resolvedSource === null ? resolvedSource : resolvedSource[part];
5897
+ resolvedSchema = resolvedSchema instanceof ObjectSchema ? resolvedSchema["items"][part] : resolvedSchema.items[part];
5898
+ // } else if (isI18nSchema(resolvedSchema)) {
5899
+ // if (!resolvedSchema.locales.includes(part)) {
5900
+ // throw Error(
5901
+ // `Invalid path: i18n schema ${resolvedSchema} supports locales ${resolvedSchema.locales.join(
5902
+ // ", "
5181
5903
  // )}, but found: ${part}`
5182
5904
  // );
5183
5905
  // }
@@ -5378,6 +6100,21 @@ function safeResolvePath(path, valModule, schema) {
5378
6100
  }
5379
6101
  };
5380
6102
  }
6103
+ } else if (isSettingsSchema(resolvedSchema)) {
6104
+ if (resolvedSource !== null && resolvedSource !== undefined && _typeof(resolvedSource) !== "object") {
6105
+ return {
6106
+ v: {
6107
+ status: "error",
6108
+ message: "Schema type error: expected source to be type of object, but got ".concat(_typeof(resolvedSource))
6109
+ }
6110
+ };
6111
+ }
6112
+ // Absent is a value here — see the note in `resolvePath`. `undefined` has
6113
+ // to be let through as well as `null`: descending into a section the
6114
+ // project has not set produces one, and the NEXT part then arrives with
6115
+ // an undefined source that is not an error either.
6116
+ resolvedSource = resolvedSource === null || resolvedSource === undefined ? resolvedSource : resolvedSource[part];
6117
+ resolvedSchema = resolvedSchema instanceof SettingsSchema ? resolvedSchema["items"][part] : resolvedSchema.items[part];
5381
6118
  } else if (isObjectSchema(resolvedSchema)) {
5382
6119
  if (resolvedSource === undefined) {
5383
6120
  return {
@@ -5565,243 +6302,44 @@ function splitModulePath(input) {
5565
6302
  }
5566
6303
  return result;
5567
6304
  }
5568
- function splitJoinedSourcePaths(input) {
5569
- // TODO: This is a very simple implementation that does not handle escaped commas
5570
- return input.split(",");
5571
- }
5572
- function parentOfSourcePath(sourcePath) {
5573
- var _splitModuleFilePathA = splitModuleFilePathAndModulePath(sourcePath),
5574
- _splitModuleFilePathA2 = _slicedToArray(_splitModuleFilePathA, 2),
5575
- moduleFilePath = _splitModuleFilePathA2[0],
5576
- modulePath = _splitModuleFilePathA2[1];
5577
- var modulePathParts = splitModulePath(modulePath).slice(0, -1);
5578
- if (modulePathParts.length > 0) {
5579
- return joinModuleFilePathAndModulePath(moduleFilePath, patchPathToModulePath(modulePathParts));
5580
- }
5581
- return moduleFilePath;
5582
- }
5583
- function patchPathToModulePath(patchPath) {
5584
- return patchPath.map(function (segment) {
5585
- // TODO: I am worried that something is lost here: what if the segment is a string that happens to be a parsable as a number? We could make those keys illegal?
5586
- if (Number.isInteger(Number(segment))) {
5587
- return segment;
5588
- }
5589
- return JSON.stringify(segment);
5590
- }).join(".");
5591
- }
5592
-
5593
- var NumberSchema = /*#__PURE__*/function (_Schema) {
5594
- function NumberSchema(options) {
5595
- var _this;
5596
- var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
5597
- var customValidateFunctions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
5598
- var isReadonly = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
5599
- var isHidden = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
5600
- var description = arguments.length > 5 ? arguments[5] : undefined;
5601
- var renderInput = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
5602
- var previewInput = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null;
5603
- _classCallCheck(this, NumberSchema);
5604
- _this = _callSuper(this, NumberSchema);
5605
- _this.options = options;
5606
- _this.opt = opt;
5607
- _this.customValidateFunctions = customValidateFunctions;
5608
- _this.isReadonly = isReadonly;
5609
- _this.isHidden = isHidden;
5610
- _this.description = description;
5611
- _this.renderInput = renderInput;
5612
- _this.previewInput = previewInput;
5613
- return _this;
5614
- }
5615
- _inherits(NumberSchema, _Schema);
5616
- return _createClass(NumberSchema, [{
5617
- key: "describe",
5618
- value: function describe(description) {
5619
- return new NumberSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
5620
- }
5621
- }, {
5622
- key: "validate",
5623
- value: function validate(validationFunction) {
5624
- return new NumberSchema(this.options, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
5625
- }
5626
- }, {
5627
- key: "executeValidate",
5628
- value: function executeValidate(path, src) {
5629
- var _this$options, _this$options2;
5630
- var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
5631
- path: path
5632
- });
5633
- if (this.opt && (src === null || src === undefined)) {
5634
- return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
5635
- }
5636
- if (typeof src !== "number") {
5637
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
5638
- message: "Expected 'number', got '".concat(_typeof(src), "'"),
5639
- value: src
5640
- }]));
5641
- }
5642
- if ((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.max && src > this.options.max) {
5643
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
5644
- message: "Expected 'number' less than ".concat(this.options.max),
5645
- value: src
5646
- }]));
5647
- }
5648
- if ((_this$options2 = this.options) !== null && _this$options2 !== void 0 && _this$options2.min && src < this.options.min) {
5649
- return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
5650
- message: "Expected 'number' greater than ".concat(this.options.min),
5651
- value: src
5652
- }]));
5653
- }
5654
- if (customValidationErrors.length > 0) {
5655
- return _defineProperty({}, path, customValidationErrors);
5656
- }
5657
- return false;
5658
- }
5659
- }, {
5660
- key: "executeAssert",
5661
- value: function executeAssert(path, src) {
5662
- if (this.opt && src === null) {
5663
- return {
5664
- success: true,
5665
- data: src
5666
- };
5667
- }
5668
- if (src === null) {
5669
- return {
5670
- success: false,
5671
- errors: _defineProperty({}, path, [{
5672
- message: "Expected 'number', got 'null'",
5673
- typeError: true
5674
- }])
5675
- };
5676
- }
5677
- if (typeof src === "number") {
5678
- return {
5679
- success: true,
5680
- data: src
5681
- };
5682
- }
5683
- return {
5684
- success: false,
5685
- errors: _defineProperty({}, path, [{
5686
- message: "Expected 'number', got '".concat(_typeof(src), "'"),
5687
- typeError: true
5688
- }])
5689
- };
5690
- }
5691
- }, {
5692
- key: "nullable",
5693
- value: function nullable() {
5694
- return new NumberSchema(this.options, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
5695
- }
5696
- }, {
5697
- key: "readonly",
5698
- value: function readonly() {
5699
- return new NumberSchema(this.options, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
5700
- }
5701
- }, {
5702
- key: "hidden",
5703
- value: function hidden() {
5704
- return new NumberSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
5705
- }
5706
- }, {
5707
- key: "max",
5708
- value: function max(_max) {
5709
- return new NumberSchema(_objectSpread2(_objectSpread2({}, this.options), {}, {
5710
- max: _max
5711
- }), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
5712
- }
5713
- }, {
5714
- key: "min",
5715
- value: function min(_min) {
5716
- return new NumberSchema(_objectSpread2(_objectSpread2({}, this.options), {}, {
5717
- min: _min
5718
- }), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
5719
- }
5720
- }, {
5721
- key: "executeCustomValidateAt",
5722
- value: function executeCustomValidateAt(path, src) {
5723
- return this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
5724
- path: path
5725
- });
5726
- }
5727
-
5728
- /**
5729
- * How this field is laid out in the editor when it is the item of an array
5730
- * or record: `{ as: "inline" }` renders the field itself inside each row,
5731
- * instead of a preview row that navigates to it.
5732
- *
5733
- * Static configuration, not a callback — see `render.ts`.
5734
- */
5735
- }, {
5736
- key: "render",
5737
- value: function render(input) {
5738
- return new NumberSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, input, this.previewInput);
5739
- }
5740
-
5741
- /**
5742
- * How this VALUE is shown where a preview of it is needed — a row in a
5743
- * sortable list, a reference dropdown, a search hit. Never how the field
5744
- * itself is edited (that is `render`). See `preview.ts`.
5745
- */
5746
- }, {
5747
- key: "preview",
5748
- value: function preview(select) {
5749
- return new NumberSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, select);
5750
- }
5751
- }, {
5752
- key: "executePreviewItem",
5753
- value: function executePreviewItem(src) {
5754
- if (this.previewInput === null) {
5755
- return null;
5756
- }
5757
- return this.previewInput({
5758
- val: src
5759
- });
5760
- }
5761
- }, {
5762
- key: "declaresItemPreview",
5763
- value: function declaresItemPreview() {
5764
- return this.previewInput !== null;
5765
- }
5766
- }, {
5767
- key: "executeSerialize",
5768
- value: function executeSerialize() {
5769
- var _this$renderInput, _this$customValidateF;
5770
- return {
5771
- type: "number",
5772
- render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
5773
- preview: this.previewInput ? true : undefined,
5774
- options: this.options,
5775
- opt: this.opt,
5776
- customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
5777
- readonly: this.isReadonly,
5778
- hidden: this.isHidden,
5779
- description: this.description
5780
- };
5781
- }
5782
- }, {
5783
- key: "executePreview",
5784
- value: function executePreview() {
5785
- return {};
6305
+ function splitJoinedSourcePaths(input) {
6306
+ // TODO: This is a very simple implementation that does not handle escaped commas
6307
+ return input.split(",");
6308
+ }
6309
+ function parentOfSourcePath(sourcePath) {
6310
+ var _splitModuleFilePathA = splitModuleFilePathAndModulePath(sourcePath),
6311
+ _splitModuleFilePathA2 = _slicedToArray(_splitModuleFilePathA, 2),
6312
+ moduleFilePath = _splitModuleFilePathA2[0],
6313
+ modulePath = _splitModuleFilePathA2[1];
6314
+ var modulePathParts = splitModulePath(modulePath).slice(0, -1);
6315
+ if (modulePathParts.length > 0) {
6316
+ return joinModuleFilePathAndModulePath(moduleFilePath, patchPathToModulePath(modulePathParts));
6317
+ }
6318
+ return moduleFilePath;
6319
+ }
6320
+ function patchPathToModulePath(patchPath) {
6321
+ return patchPath.map(function (segment) {
6322
+ // TODO: I am worried that something is lost here: what if the segment is a string that happens to be a parsable as a number? We could make those keys illegal?
6323
+ if (Number.isInteger(Number(segment))) {
6324
+ return segment;
5786
6325
  }
5787
- }]);
5788
- }(Schema);
5789
- var number = function number(options) {
5790
- return new NumberSchema(options);
5791
- };
6326
+ return JSON.stringify(segment);
6327
+ }).join(".");
6328
+ }
5792
6329
 
5793
- var BooleanSchema = /*#__PURE__*/function (_Schema) {
5794
- function BooleanSchema() {
6330
+ var NumberSchema = /*#__PURE__*/function (_Schema) {
6331
+ function NumberSchema(options) {
5795
6332
  var _this;
5796
- var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
5797
- var customValidateFunctions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
5798
- var isReadonly = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
5799
- var isHidden = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
5800
- var description = arguments.length > 4 ? arguments[4] : undefined;
5801
- var renderInput = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;
5802
- var previewInput = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
5803
- _classCallCheck(this, BooleanSchema);
5804
- _this = _callSuper(this, BooleanSchema);
6333
+ var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
6334
+ var customValidateFunctions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
6335
+ var isReadonly = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
6336
+ var isHidden = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
6337
+ var description = arguments.length > 5 ? arguments[5] : undefined;
6338
+ var renderInput = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
6339
+ var previewInput = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null;
6340
+ _classCallCheck(this, NumberSchema);
6341
+ _this = _callSuper(this, NumberSchema);
6342
+ _this.options = options;
5805
6343
  _this.opt = opt;
5806
6344
  _this.customValidateFunctions = customValidateFunctions;
5807
6345
  _this.isReadonly = isReadonly;
@@ -5811,28 +6349,47 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
5811
6349
  _this.previewInput = previewInput;
5812
6350
  return _this;
5813
6351
  }
5814
- _inherits(BooleanSchema, _Schema);
5815
- return _createClass(BooleanSchema, [{
6352
+ _inherits(NumberSchema, _Schema);
6353
+ return _createClass(NumberSchema, [{
5816
6354
  key: "describe",
5817
6355
  value: function describe(description) {
5818
- return new BooleanSchema(this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
6356
+ return new NumberSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, description !== null && description !== void 0 ? description : undefined, this.renderInput, this.previewInput);
5819
6357
  }
5820
6358
  }, {
5821
6359
  key: "validate",
5822
6360
  value: function validate(validationFunction) {
5823
- return new BooleanSchema(this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
6361
+ return new NumberSchema(this.options, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]), this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
5824
6362
  }
5825
6363
  }, {
5826
6364
  key: "executeValidate",
5827
6365
  value: function executeValidate(path, src) {
6366
+ var _this$options, _this$options2;
6367
+ var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
6368
+ path: path
6369
+ });
5828
6370
  if (this.opt && (src === null || src === undefined)) {
5829
- return false;
6371
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
5830
6372
  }
5831
- if (typeof src !== "boolean") {
5832
- return _defineProperty({}, path, [{
5833
- message: "Expected 'boolean', got '".concat(_typeof(src), "'"),
6373
+ if (typeof src !== "number") {
6374
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
6375
+ message: "Expected 'number', got '".concat(_typeof(src), "'"),
5834
6376
  value: src
5835
- }]);
6377
+ }]));
6378
+ }
6379
+ if ((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.max && src > this.options.max) {
6380
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
6381
+ message: "Expected 'number' less than ".concat(this.options.max),
6382
+ value: src
6383
+ }]));
6384
+ }
6385
+ if ((_this$options2 = this.options) !== null && _this$options2 !== void 0 && _this$options2.min && src < this.options.min) {
6386
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
6387
+ message: "Expected 'number' greater than ".concat(this.options.min),
6388
+ value: src
6389
+ }]));
6390
+ }
6391
+ if (customValidationErrors.length > 0) {
6392
+ return _defineProperty({}, path, customValidationErrors);
5836
6393
  }
5837
6394
  return false;
5838
6395
  }
@@ -5849,39 +6406,55 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
5849
6406
  return {
5850
6407
  success: false,
5851
6408
  errors: _defineProperty({}, path, [{
5852
- message: "Expected 'boolean', got 'null'",
6409
+ message: "Expected 'number', got 'null'",
5853
6410
  typeError: true
5854
6411
  }])
5855
6412
  };
5856
6413
  }
5857
- if (typeof src !== "boolean") {
6414
+ if (typeof src === "number") {
5858
6415
  return {
5859
- success: false,
5860
- errors: _defineProperty({}, path, [{
5861
- message: "Expected 'boolean', got '".concat(_typeof(src), "'"),
5862
- typeError: true
5863
- }])
6416
+ success: true,
6417
+ data: src
5864
6418
  };
5865
6419
  }
5866
6420
  return {
5867
- success: true,
5868
- data: src
6421
+ success: false,
6422
+ errors: _defineProperty({}, path, [{
6423
+ message: "Expected 'number', got '".concat(_typeof(src), "'"),
6424
+ typeError: true
6425
+ }])
5869
6426
  };
5870
6427
  }
5871
6428
  }, {
5872
6429
  key: "nullable",
5873
6430
  value: function nullable() {
5874
- return new BooleanSchema(true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
6431
+ return new NumberSchema(this.options, true, [], this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
5875
6432
  }
5876
6433
  }, {
5877
6434
  key: "readonly",
5878
6435
  value: function readonly() {
5879
- return new BooleanSchema(this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
6436
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
6437
+ return new NumberSchema(this.options, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
5880
6438
  }
5881
6439
  }, {
5882
6440
  key: "hidden",
5883
6441
  value: function hidden() {
5884
- return new BooleanSchema(this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
6442
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
6443
+ return new NumberSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
6444
+ }
6445
+ }, {
6446
+ key: "max",
6447
+ value: function max(_max) {
6448
+ return new NumberSchema(_objectSpread2(_objectSpread2({}, this.options), {}, {
6449
+ max: _max
6450
+ }), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
6451
+ }
6452
+ }, {
6453
+ key: "min",
6454
+ value: function min(_min) {
6455
+ return new NumberSchema(_objectSpread2(_objectSpread2({}, this.options), {}, {
6456
+ min: _min
6457
+ }), this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
5885
6458
  }
5886
6459
  }, {
5887
6460
  key: "executeCustomValidateAt",
@@ -5901,7 +6474,7 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
5901
6474
  }, {
5902
6475
  key: "render",
5903
6476
  value: function render(input) {
5904
- return new BooleanSchema(this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, input, this.previewInput);
6477
+ return new NumberSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, input, this.previewInput);
5905
6478
  }
5906
6479
 
5907
6480
  /**
@@ -5912,7 +6485,7 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
5912
6485
  }, {
5913
6486
  key: "preview",
5914
6487
  value: function preview(select) {
5915
- return new BooleanSchema(this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, select);
6488
+ return new NumberSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, this.isHidden, this.description, this.renderInput, select);
5916
6489
  }
5917
6490
  }, {
5918
6491
  key: "executePreviewItem",
@@ -5934,9 +6507,10 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
5934
6507
  value: function executeSerialize() {
5935
6508
  var _this$renderInput, _this$customValidateF;
5936
6509
  return {
5937
- type: "boolean",
6510
+ type: "number",
5938
6511
  render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
5939
6512
  preview: this.previewInput ? true : undefined,
6513
+ options: this.options,
5940
6514
  opt: this.opt,
5941
6515
  customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
5942
6516
  readonly: this.isReadonly,
@@ -5951,8 +6525,8 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
5951
6525
  }
5952
6526
  }]);
5953
6527
  }(Schema);
5954
- var _boolean = function _boolean() {
5955
- return new BooleanSchema();
6528
+ var number = function number(options) {
6529
+ return new NumberSchema(options);
5956
6530
  };
5957
6531
 
5958
6532
  var KeyOfSchema = /*#__PURE__*/function (_Schema) {
@@ -6122,12 +6696,14 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
6122
6696
  }, {
6123
6697
  key: "readonly",
6124
6698
  value: function readonly() {
6125
- return new KeyOfSchema(this.schema, this.sourcePath, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
6699
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
6700
+ return new KeyOfSchema(this.schema, this.sourcePath, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
6126
6701
  }
6127
6702
  }, {
6128
6703
  key: "hidden",
6129
6704
  value: function hidden() {
6130
- return new KeyOfSchema(this.schema, this.sourcePath, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
6705
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
6706
+ return new KeyOfSchema(this.schema, this.sourcePath, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
6131
6707
  }
6132
6708
  }, {
6133
6709
  key: "executeCustomValidateAt",
@@ -6464,12 +7040,14 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
6464
7040
  }, {
6465
7041
  key: "readonly",
6466
7042
  value: function readonly() {
6467
- return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, true, this.isHidden, this.description, this.renderInput, this.previewInput);
7043
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
7044
+ return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
6468
7045
  }
6469
7046
  }, {
6470
7047
  key: "hidden",
6471
7048
  value: function hidden() {
6472
- return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
7049
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
7050
+ return new FileSchema(this.options, this.opt, this.isRemote, this.customValidateFunctions, this.moduleMetadata, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
6473
7051
  }
6474
7052
  }, {
6475
7053
  key: "executeCustomValidateAt",
@@ -6579,6 +7157,8 @@ function file(options) {
6579
7157
  /**
6580
7158
  * Define a collection of files.
6581
7159
  *
7160
+ * Remote is off by default: call `.remote()` on the result to allow remote files.
7161
+ *
6582
7162
  * @example
6583
7163
  * ```typescript
6584
7164
  * const schema = s.files({
@@ -6593,7 +7173,6 @@ function file(options) {
6593
7173
  * ```
6594
7174
  */
6595
7175
  var files = function files(options) {
6596
- var _options$remote;
6597
7176
  var directory = options.directory;
6598
7177
  var itemSchema = new ObjectSchema({
6599
7178
  mimeType: new StringSchema({}, false)
@@ -6602,7 +7181,7 @@ var files = function files(options) {
6602
7181
  type: "files",
6603
7182
  accept: options.accept,
6604
7183
  directory: directory,
6605
- remote: (_options$remote = options.remote) !== null && _options$remote !== void 0 ? _options$remote : false
7184
+ remote: false
6606
7185
  });
6607
7186
  };
6608
7187
 
@@ -6743,12 +7322,14 @@ var DateSchema = /*#__PURE__*/function (_Schema) {
6743
7322
  }, {
6744
7323
  key: "readonly",
6745
7324
  value: function readonly() {
6746
- return new DateSchema(this.options, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
7325
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
7326
+ return new DateSchema(this.options, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
6747
7327
  }
6748
7328
  }, {
6749
7329
  key: "hidden",
6750
7330
  value: function hidden() {
6751
- return new DateSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
7331
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
7332
+ return new DateSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
6752
7333
  }
6753
7334
  }, {
6754
7335
  key: "executeCustomValidateAt",
@@ -6992,12 +7573,14 @@ var DateTimeSchema = /*#__PURE__*/function (_Schema) {
6992
7573
  }, {
6993
7574
  key: "readonly",
6994
7575
  value: function readonly() {
6995
- return new DateTimeSchema(this.options, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
7576
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
7577
+ return new DateTimeSchema(this.options, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
6996
7578
  }
6997
7579
  }, {
6998
7580
  key: "hidden",
6999
7581
  value: function hidden() {
7000
- return new DateTimeSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
7582
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
7583
+ return new DateTimeSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
7001
7584
  }
7002
7585
  }, {
7003
7586
  key: "executeCustomValidateAt",
@@ -7177,12 +7760,14 @@ var CodeSchema = /*#__PURE__*/function (_Schema) {
7177
7760
  }, {
7178
7761
  key: "readonly",
7179
7762
  value: function readonly() {
7180
- return new CodeSchema(this.options, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
7763
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
7764
+ return new CodeSchema(this.options, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
7181
7765
  }
7182
7766
  }, {
7183
7767
  key: "hidden",
7184
7768
  value: function hidden() {
7185
- return new CodeSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
7769
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
7770
+ return new CodeSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
7186
7771
  }
7187
7772
 
7188
7773
  /**
@@ -7863,12 +8448,14 @@ var ColorSchema = /*#__PURE__*/function (_Schema) {
7863
8448
  }, {
7864
8449
  key: "readonly",
7865
8450
  value: function readonly() {
7866
- return new ColorSchema(this.options, this.opt, this.customValidateFunctions, true, this.isHidden, this.description, this.renderInput, this.previewInput);
8451
+ var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
8452
+ return new ColorSchema(this.options, this.opt, this.customValidateFunctions, isReadonly, this.isHidden, this.description, this.renderInput, this.previewInput);
7867
8453
  }
7868
8454
  }, {
7869
8455
  key: "hidden",
7870
8456
  value: function hidden() {
7871
- return new ColorSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, true, this.description, this.renderInput, this.previewInput);
8457
+ var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
8458
+ return new ColorSchema(this.options, this.opt, this.customValidateFunctions, this.isReadonly, isHidden, this.description, this.renderInput, this.previewInput);
7872
8459
  }
7873
8460
 
7874
8461
  /**
@@ -7962,7 +8549,7 @@ function router(router, keyOrItem, maybeItem) {
7962
8549
  *
7963
8550
  * `directory` is required — it decides where uploads land, so it is not something
7964
8551
  * to be inferred. The rest defaults: any image type (`"image/*"`), nullable alt
7965
- * text, remote disabled.
8552
+ * text, remote disabled. Call `.remote()` on the result to allow remote images.
7966
8553
  *
7967
8554
  * @example
7968
8555
  * ```typescript
@@ -7982,7 +8569,7 @@ function router(router, keyOrItem, maybeItem) {
7982
8569
  * ```
7983
8570
  */
7984
8571
  var images = function images(options) {
7985
- var _options$alt, _options$accept, _options$remote;
8572
+ var _options$alt, _options$accept;
7986
8573
  var directory = options.directory;
7987
8574
  var altSchema = (_options$alt = options.alt) !== null && _options$alt !== void 0 ? _options$alt : string().nullable();
7988
8575
  var itemSchema = new ObjectSchema({
@@ -7995,7 +8582,7 @@ var images = function images(options) {
7995
8582
  type: "images",
7996
8583
  accept: (_options$accept = options.accept) !== null && _options$accept !== void 0 ? _options$accept : "image/*",
7997
8584
  directory: directory,
7998
- remote: (_options$remote = options.remote) !== null && _options$remote !== void 0 ? _options$remote : false,
8585
+ remote: false,
7999
8586
  altSchema: altSchema,
8000
8587
  encode: options.encode
8001
8588
  });
@@ -8031,7 +8618,8 @@ function initSchema() {
8031
8618
  code: code,
8032
8619
  route: route,
8033
8620
  router: router,
8034
- images: images
8621
+ images: images,
8622
+ settings: settings
8035
8623
  // i18n: i18n(locales),
8036
8624
  };
8037
8625
  }
@@ -8072,7 +8660,8 @@ var initVal = function initVal(config) {
8072
8660
  },
8073
8661
  c: {
8074
8662
  define: define,
8075
- json: json
8663
+ json: json,
8664
+ external: external
8076
8665
  },
8077
8666
  s: s,
8078
8667
  config: config
@@ -8432,6 +9021,98 @@ var getSHA256Hash = function getSHA256Hash(bits) {
8432
9021
  return createHash().update(bits).digest("hex");
8433
9022
  };
8434
9023
 
9024
+ /**
9025
+ * Where a settings module goes unless a project has a reason not to.
9026
+ *
9027
+ * A convention, not a rule: any module file path at the root of the content
9028
+ * tree may hold `s.settings()` — see {@link resolveSettingsModule}.
9029
+ */
9030
+ var SETTINGS_MODULE_CONVENTION = "/settings.val.ts";
9031
+
9032
+ /**
9033
+ * Whether a module file path is at the root of the content tree.
9034
+ *
9035
+ * `/settings.val.ts` is; `/content/settings.val.ts` is not. The settings module
9036
+ * is the project's, not a folder's, and a project-wide setting found three
9037
+ * directories down reads as one section's — so the position is part of what it
9038
+ * means.
9039
+ */
9040
+ function isRootModuleFilePath(moduleFilePath) {
9041
+ return moduleFilePath.startsWith("/") && !moduleFilePath.slice(1).includes("/");
9042
+ }
9043
+
9044
+ /**
9045
+ * Structurally an `ExtractedModuleError`, declared here rather than imported to
9046
+ * keep `extractValModules` -> `settingsModule` a one-way dependency.
9047
+ */
9048
+
9049
+ /**
9050
+ * Find the project's settings module among all its schemas.
9051
+ *
9052
+ * One per project, at the root: a settings module in a subdirectory is an
9053
+ * error, and so is a second one. Both are reported rather than resolved by
9054
+ * picking a winner — a project with two settings modules has a question to
9055
+ * answer, and answering it by sort order means the answer changes when a file
9056
+ * is renamed.
9057
+ */
9058
+ function resolveSettingsModule(schemas) {
9059
+ var rootModules = [];
9060
+ var nestedModules = [];
9061
+ var _iterator = result._createForOfIteratorHelper(Object.keys(schemas).sort()),
9062
+ _step;
9063
+ try {
9064
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
9065
+ var _schemas$_moduleFileP;
9066
+ var moduleFilePathS = _step.value;
9067
+ var _moduleFilePath2 = moduleFilePathS;
9068
+ if (((_schemas$_moduleFileP = schemas[_moduleFilePath2]) === null || _schemas$_moduleFileP === void 0 ? void 0 : _schemas$_moduleFileP.type) !== "settings") {
9069
+ continue;
9070
+ }
9071
+ if (isRootModuleFilePath(_moduleFilePath2)) {
9072
+ rootModules.push(_moduleFilePath2);
9073
+ } else {
9074
+ nestedModules.push(_moduleFilePath2);
9075
+ }
9076
+ }
9077
+ } catch (err) {
9078
+ _iterator.e(err);
9079
+ } finally {
9080
+ _iterator.f();
9081
+ }
9082
+ var errors = [];
9083
+ for (var _i = 0, _nestedModules = nestedModules; _i < _nestedModules.length; _i++) {
9084
+ var moduleFilePath = _nestedModules[_i];
9085
+ errors.push({
9086
+ path: moduleFilePath,
9087
+ message: "Settings must be defined at the root of the content tree, but s.settings() was found in '".concat(moduleFilePath, "'. Move it to a module file path with no directory in it, e.g. '").concat(SETTINGS_MODULE_CONVENTION, "'.")
9088
+ });
9089
+ }
9090
+ if (rootModules.length > 1) {
9091
+ var listed = rootModules.map(function (moduleFilePath) {
9092
+ return "'".concat(moduleFilePath, "'");
9093
+ }).join(" and ");
9094
+ var _iterator2 = result._createForOfIteratorHelper(rootModules),
9095
+ _step2;
9096
+ try {
9097
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
9098
+ var _moduleFilePath = _step2.value;
9099
+ errors.push({
9100
+ path: _moduleFilePath,
9101
+ message: "A project can only define settings once, but s.settings() was found in ".concat(listed, ". Keep one of them.")
9102
+ });
9103
+ }
9104
+ } catch (err) {
9105
+ _iterator2.e(err);
9106
+ } finally {
9107
+ _iterator2.f();
9108
+ }
9109
+ }
9110
+ return {
9111
+ moduleFilePath: errors.length === 0 && rootModules.length === 1 ? rootModules[0] : null,
9112
+ errors: errors
9113
+ };
9114
+ }
9115
+
8435
9116
  // Lazily constructed: this module is also evaluated inside the `vm` sandbox
8436
9117
  // used by loadValModules (when user val modules import @valbuild/core), and
8437
9118
  // that sandbox has no `TextEncoder` global. `hash()` is never called from
@@ -8599,7 +9280,7 @@ function extractValModules(_x) {
8599
9280
  }
8600
9281
  function _extractValModules() {
8601
9282
  _extractValModules = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(valModules) {
8602
- var moduleErrors, addModuleError, sources, schemas, serializedSchemas, shaEntries, moduleIdx, module, at, value, path, schema, source, serializedSchema, pathM, _t, _t2;
9283
+ var moduleErrors, addModuleError, sources, schemas, serializedSchemas, shaEntries, moduleIdx, module, at, value, path, schema, source, serializedSchema, pathM, _iterator2, _step2, error, _t, _t2;
8603
9284
  return _regenerator().w(function (_context) {
8604
9285
  while (1) switch (_context.p = _context.n) {
8605
9286
  case 0:
@@ -8738,6 +9419,25 @@ function _extractValModules() {
8738
9419
  _context.n = 1;
8739
9420
  break;
8740
9421
  case 18:
9422
+ // Settings is the one rule that cannot be checked while looking at a single
9423
+ // module: "one per project, at the root" is a statement about the whole set.
9424
+ // Reported here so that every consumer of extraction gets it — the dev
9425
+ // server, `val validate` and the Studio all read `moduleErrors`.
9426
+ //
9427
+ // Appended AFTER the loop on purpose: each entry's `moduleErrorsAt` is the
9428
+ // error count at the time it was folded in, so the SHAs stay a function of
9429
+ // the modules themselves.
9430
+ _iterator2 = result._createForOfIteratorHelper(resolveSettingsModule(serializedSchemas).errors);
9431
+ try {
9432
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
9433
+ error = _step2.value;
9434
+ moduleErrors.push(error);
9435
+ }
9436
+ } catch (err) {
9437
+ _iterator2.e(err);
9438
+ } finally {
9439
+ _iterator2.f();
9440
+ }
8741
9441
  return _context.a(2, _objectSpread2(_objectSpread2({
8742
9442
  sources: sources,
8743
9443
  schemas: schemas,
@@ -8758,9 +9458,10 @@ function _extractValModules() {
8758
9458
  * The one answer to that question. There used to be two — `hasRemoteFileSchema`
8759
9459
  * in the server, gating whether `/save` demands remote credentials, and
8760
9460
  * `findRequiredRemoteFiles` in the Studio, gating the `/remote/settings` fetch —
8761
- * and they disagreed about `s.images({ remote: true })`: the Studio's counted a
8762
- * remote media record, the server's did not, because a media collection
8763
- * serializes as a `record` of metadata rather than as an image schema.
9461
+ * and they disagreed about `s.images({ ... }).remote()`: the Studio's version
9462
+ * counted a remote media record, the server's did not, because a media
9463
+ * collection serializes as a `record` of metadata rather than as an image
9464
+ * schema.
8764
9465
  *
8765
9466
  * The server's answer was the wrong one, and silently so. With it false,
8766
9467
  * `/save` runs `saveOrUploadFiles` in `skip-remote` mode, and that mode does not
@@ -8809,7 +9510,10 @@ function hasRemoteFileSchema(schema) {
8809
9510
  return true;
8810
9511
  }
8811
9512
  return hasRemoteFileSchema(schema.item);
8812
- } else if (schema.type === "object") {
9513
+ } else if (schema.type === "object" || schema.type === "settings") {
9514
+ // Settings holds its sections the way an object holds its keys, so looking
9515
+ // inside is the same walk. Nothing in settings takes a file today, but the
9516
+ // answer should stay right when something does.
8813
9517
  for (var key in schema.items) {
8814
9518
  var hasRemoteFile = hasRemoteFileSchema(schema.items[key]);
8815
9519
  if (hasRemoteFile) {
@@ -8850,6 +9554,85 @@ function hasRemoteFileSchema(schema) {
8850
9554
  }
8851
9555
  }
8852
9556
 
9557
+ /**
9558
+ * Does this schema hold any media at all — remote or not?
9559
+ *
9560
+ * The sibling of {@link hasRemoteFileSchema}, and the same walk minus the
9561
+ * `remote` predicate. It answers the question an external record has to ask
9562
+ * before it will accept a binding: an item schema containing media needs a
9563
+ * `putFile`/`getFile` pair, and without one that is a schema error.
9564
+ *
9565
+ * It is a walk over the SERIALIZED schema for the reasons given above, and for
9566
+ * one more that is specific to this question: the two cases most likely to be
9567
+ * missed are invisible to a value type. A media collection (`s.images()` /
9568
+ * `s.files()`) serializes as a record of metadata with no image schema inside
9569
+ * it, and a richtext inline image lives in a constructor argument. A check
9570
+ * written against the item TYPE would silently pass both — and the gallery case
9571
+ * already has a data-loss incident attached to it (see above).
9572
+ */
9573
+ function hasMediaSchema(schema) {
9574
+ if (schema.type === "file" || schema.type === "image") {
9575
+ return true;
9576
+ } else if (schema.type === "richtext") {
9577
+ var _schema$options2;
9578
+ // `img` is `boolean | SerializedImageSchema`: `true` means inline images are
9579
+ // allowed with the DEFAULT image schema, and is just as much media as a
9580
+ // spelled-out one. `hasRemoteFileSchema` tests only for an object because a
9581
+ // default image is not remote — a different question with a different
9582
+ // answer, which is why these two walks are separate functions.
9583
+ if ((_schema$options2 = schema.options) !== null && _schema$options2 !== void 0 && _schema$options2.img) {
9584
+ return true;
9585
+ }
9586
+ return false;
9587
+ } else if (schema.type === "array") {
9588
+ return hasMediaSchema(schema.item);
9589
+ } else if (schema.type === "record") {
9590
+ // A media collection names its file by the record's KEY, so there is no
9591
+ // image schema inside to find: `mediaType` is where the answer is written.
9592
+ if (schema.mediaType) {
9593
+ return true;
9594
+ }
9595
+ return hasMediaSchema(schema.item);
9596
+ } else if (schema.type === "object") {
9597
+ for (var key in schema.items) {
9598
+ if (hasMediaSchema(schema.items[key])) {
9599
+ return true;
9600
+ }
9601
+ }
9602
+ return false;
9603
+ } else if (schema.type === "union") {
9604
+ var unionObjectSchema = typeof schema.key === "string" ? schema : undefined;
9605
+ if (unionObjectSchema) {
9606
+ var _iterator2 = result._createForOfIteratorHelper(unionObjectSchema.items),
9607
+ _step2;
9608
+ try {
9609
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
9610
+ var item = _step2.value;
9611
+ if (hasMediaSchema(item)) {
9612
+ return true;
9613
+ }
9614
+ }
9615
+ } catch (err) {
9616
+ _iterator2.e(err);
9617
+ } finally {
9618
+ _iterator2.f();
9619
+ }
9620
+ }
9621
+ // A string union's items are literals, so there is nothing to look inside.
9622
+ return false;
9623
+ } else if (schema.type === "boolean" || 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" ||
9624
+ // A settings module holds the assistant's configuration, not content, and
9625
+ // nothing in it is media.
9626
+ schema.type === "settings") {
9627
+ return false;
9628
+ } else {
9629
+ // Same contract as above: adding a schema type without teaching this
9630
+ // function about it must not compile.
9631
+ var exhaustiveCheck = schema;
9632
+ throw new Error("Unexpected schema: ".concat(JSON.stringify(exhaustiveCheck)));
9633
+ }
9634
+ }
9635
+
8853
9636
  var DEFAULT_VAL_REMOTE_HOST = "https://remote.val.build";
8854
9637
 
8855
9638
  var PatchError = /*#__PURE__*/_createClass(function PatchError(message) {
@@ -8994,6 +9777,79 @@ function mediaPathOf(value) {
8994
9777
  return typeof path === "string" ? path : null;
8995
9778
  }
8996
9779
 
9780
+ /**
9781
+ * The reference stored for a file whose bytes live behind an external adapter.
9782
+ *
9783
+ * Deliberately the same shape of idea as a remote ref (`remote/splitRemoteRef`):
9784
+ * a URL-ish string that **ends with the file's virtual path**, so the file's
9785
+ * logical identity survives wherever its bytes happen to be.
9786
+ *
9787
+ * /api/val/external/documents/f/{fileHash}/p/public/val/documents/report_a1b2c.pdf
9788
+ * \__________________________/ \________/ \_______________________________/
9789
+ * route + label content the path a LOCAL file
9790
+ * address would have had
9791
+ *
9792
+ * Three things follow from that shape, and each is load-bearing:
9793
+ *
9794
+ * - **`media.ts` needs no change.** `isRemote` is `!path.startsWith("/public")`,
9795
+ * and this does not, so `Internal.mediaUrl` returns the ref as-is and Val's
9796
+ * route serves it. The media rule that has been got wrong repeatedly is left
9797
+ * exactly alone.
9798
+ * - **Moving between storage modes is mechanical.** External → local reads the
9799
+ * `public/…` suffix back out, fetches the bytes and writes them there; local →
9800
+ * external uploads the file already at that path. Nothing is renamed.
9801
+ * - **The filename is Val's, not the adapter's**, produced by the same
9802
+ * `createFilename` a local or remote file uses — so the same bytes get the
9803
+ * same name under all three storage modes.
9804
+ */
9805
+
9806
+ var RegEx = /^\/api\/val\/external\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
9807
+ function createExternalFileRef(_ref) {
9808
+ var label = _ref.label,
9809
+ fileHash = _ref.fileHash,
9810
+ filePath = _ref.filePath;
9811
+ var withoutLeadingSlash = filePath.startsWith("/") ? filePath.slice(1) : filePath;
9812
+ if (!withoutLeadingSlash.startsWith("public/")) {
9813
+ throw new Error("External file paths must be under '/public', got: '".concat(filePath, "'"));
9814
+ }
9815
+ return "/api/val/external/".concat(label, "/f/").concat(fileHash, "/p/").concat(withoutLeadingSlash);
9816
+ }
9817
+ function splitExternalFileRef(ref) {
9818
+ var match = ref.match(RegEx);
9819
+ if (!match) {
9820
+ return {
9821
+ status: "error",
9822
+ error: "Not an external file ref: " + ref
9823
+ };
9824
+ }
9825
+ var filePath = match[3];
9826
+ if (!filePath.startsWith("public/")) {
9827
+ return {
9828
+ status: "error",
9829
+ error: "Invalid external file ref: " + ref
9830
+ };
9831
+ }
9832
+ // Traversal check, for the same reason `splitRemoteRef` has one: this path is
9833
+ // used to read and write files.
9834
+ if (filePath.split("/").some(function (segment) {
9835
+ return segment === "." || segment === "..";
9836
+ })) {
9837
+ return {
9838
+ status: "error",
9839
+ error: "Invalid external file ref: " + ref
9840
+ };
9841
+ }
9842
+ return {
9843
+ status: "success",
9844
+ label: match[1],
9845
+ fileHash: match[2],
9846
+ filePath: filePath
9847
+ };
9848
+ }
9849
+ function isExternalFileRef(ref) {
9850
+ return RegEx.test(ref);
9851
+ }
9852
+
8997
9853
  // NOTE: the segments must match the ref built by createRemoteRef below and the RegEx in splitRemoteRef.
8998
9854
 
8999
9855
  function createRemoteRef(remoteHost, _ref) {
@@ -9054,7 +9910,7 @@ function deserializeSchema(serialized) {
9054
9910
  return schema;
9055
9911
  }
9056
9912
  function deserializeSchemaImpl(serialized) {
9057
- var _serialized$options, _serialized$options2, _serialized$render, _serialized$multiline, _serialized$render2, _serialized$render3, _serialized$render4, _serialized$render5, _serialized$render6, _serialized$render7, _serialized$accept, _serialized$directory, _serialized$remote, _serialized$jsonValue, _serialized$render9, _serialized$render0, _serialized$render10, _serialized$render11, _serialized$render12, _serialized$render13, _serialized$render14, _serialized$render15;
9913
+ var _serialized$options, _serialized$options2, _serialized$render, _serialized$multiline, _serialized$render2, _serialized$render3, _serialized$render4, _serialized$render5, _serialized$render6, _serialized$render7, _serialized$accept, _serialized$directory, _serialized$remote, _serialized$jsonValue, _serialized$render9, _serialized$external, _serialized$render0, _serialized$render10, _serialized$render11, _serialized$render12, _serialized$render13, _serialized$render14, _serialized$render15;
9058
9914
  switch (serialized.type) {
9059
9915
  case "string":
9060
9916
  return new StringSchema(_objectSpread2(_objectSpread2({}, serialized.options), {}, {
@@ -9077,6 +9933,13 @@ function deserializeSchemaImpl(serialized) {
9077
9933
  item = _ref2[1];
9078
9934
  return [key, deserializeSchema(item)];
9079
9935
  })), serialized.opt, [], false, false, serialized.description, (_serialized$render5 = serialized.render) !== null && _serialized$render5 !== void 0 ? _serialized$render5 : null);
9936
+ case "settings":
9937
+ return new SettingsSchema(Object.fromEntries(Object.entries(serialized.items).map(function (_ref3) {
9938
+ var _ref4 = _slicedToArray(_ref3, 2),
9939
+ key = _ref4[0],
9940
+ item = _ref4[1];
9941
+ return [key, deserializeSchema(item)];
9942
+ })), serialized.opt, false, false, serialized.description);
9080
9943
  case "array":
9081
9944
  return new ArraySchema(deserializeSchema(serialized.item), serialized.opt, [], false, false, serialized.description,
9082
9945
  // The preview closure cannot survive serialization; the render can.
@@ -9108,7 +9971,10 @@ function deserializeSchemaImpl(serialized) {
9108
9971
  altSchema: serialized.alt ? deserializeSchema(serialized.alt) : undefined
9109
9972
  } : undefined, false, false, serialized.description, (_serialized$jsonValue = serialized.jsonValues) !== null && _serialized$jsonValue !== void 0 ? _serialized$jsonValue : false,
9110
9973
  // The preview closure cannot survive serialization; the render can.
9111
- null, (_serialized$render9 = serialized.render) !== null && _serialized$render9 !== void 0 ? _serialized$render9 : null);
9974
+ null, (_serialized$render9 = serialized.render) !== null && _serialized$render9 !== void 0 ? _serialized$render9 : null, // The external label is static data, so it survives serialization and
9975
+ // must be carried back: a deserialized schema that forgot it would walk
9976
+ // an external record as if its entries were local.
9977
+ (_serialized$external = serialized.external) !== null && _serialized$external !== void 0 ? _serialized$external : null);
9112
9978
  case "keyOf":
9113
9979
  return new KeyOfSchema(serialized.schema, serialized.path, serialized.opt, [], false, false, serialized.description, (_serialized$render0 = serialized.render) !== null && _serialized$render0 !== void 0 ? _serialized$render0 : null);
9114
9980
  case "route":
@@ -9670,6 +10536,11 @@ var Internal = {
9670
10536
  isJson: isJson,
9671
10537
  getJsonImport: getJsonImport,
9672
10538
  resolveJsonValues: resolveJsonValues,
10539
+ isExternal: isExternal,
10540
+ hasInlineExternalEntries: hasInlineExternalEntries,
10541
+ createExternalFileRef: createExternalFileRef,
10542
+ splitExternalFileRef: splitExternalFileRef,
10543
+ isExternalFileRef: isExternalFileRef,
9673
10544
  createValPathOfItem: createValPathOfItem,
9674
10545
  getSHA256Hash: getSHA256Hash,
9675
10546
  initSchema: initSchema,
@@ -9734,6 +10605,7 @@ function tryJsonParse(str) {
9734
10605
  }
9735
10606
  }
9736
10607
 
10608
+ exports.ASSISTANT_SETTINGS_MAX_LENGTH = ASSISTANT_SETTINGS_MAX_LENGTH;
9737
10609
  exports.ArraySchema = ArraySchema;
9738
10610
  exports.BooleanSchema = BooleanSchema;
9739
10611
  exports.CODE_LANGUAGES = CODE_LANGUAGES;
@@ -9760,7 +10632,9 @@ exports.PatchError = PatchError;
9760
10632
  exports.RecordSchema = RecordSchema;
9761
10633
  exports.RichTextSchema = RichTextSchema;
9762
10634
  exports.RouteSchema = RouteSchema;
10635
+ exports.SETTINGS_MODULE_CONVENTION = SETTINGS_MODULE_CONVENTION;
9763
10636
  exports.Schema = Schema;
10637
+ exports.SettingsSchema = SettingsSchema;
9764
10638
  exports.StringSchema = StringSchema;
9765
10639
  exports.UnionSchema = UnionSchema;
9766
10640
  exports.VAL_EXTENSION = VAL_EXTENSION;
@@ -9769,14 +10643,18 @@ exports._createClass = _createClass;
9769
10643
  exports._slicedToArray = _slicedToArray;
9770
10644
  exports._toConsumableArray = _toConsumableArray;
9771
10645
  exports._typeof = _typeof;
10646
+ exports.assistantAvailability = assistantAvailability;
9772
10647
  exports.computeValModuleShas = computeValModuleShas;
9773
10648
  exports.derefPatch = derefPatch;
9774
10649
  exports.deserializeSchema = deserializeSchema;
9775
10650
  exports.extractValModules = extractValModules;
9776
10651
  exports.getSourcePathFromRoute = getSourcePathFromRoute;
10652
+ exports.hasMediaSchema = hasMediaSchema;
9777
10653
  exports.hasRemoteFileSchema = hasRemoteFileSchema;
9778
10654
  exports.initVal = initVal;
9779
10655
  exports.isInlineRender = isInlineRender;
10656
+ exports.isRootModuleFilePath = isRootModuleFilePath;
9780
10657
  exports.modules = modules;
9781
10658
  exports.previewScope = previewScope;
10659
+ exports.resolveSettingsModule = resolveSettingsModule;
9782
10660
  exports.splitModuleFilePathAndModulePath = splitModuleFilePathAndModulePath;