@valbuild/core 0.121.0 → 0.125.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +110 -0
- package/dist/declarations/src/getSourcePathFromRoute.d.ts +12 -3
- package/dist/declarations/src/index.d.ts +13 -3
- package/dist/declarations/src/initVal.d.ts +2 -0
- package/dist/declarations/src/module.d.ts +18 -1
- package/dist/declarations/src/router.d.ts +45 -0
- package/dist/declarations/src/schema/files.d.ts +2 -5
- package/dist/declarations/src/schema/hasRemoteFileSchema.d.ts +21 -3
- package/dist/declarations/src/schema/images.d.ts +1 -6
- package/dist/declarations/src/schema/record.d.ts +79 -3
- package/dist/declarations/src/schema/validation/ValidationFix.d.ts +1 -1
- package/dist/declarations/src/selector/index.d.ts +3 -2
- package/dist/declarations/src/source/external.d.ts +91 -0
- package/dist/declarations/src/source/externalRef.d.ts +46 -0
- package/dist/declarations/src/source/index.d.ts +3 -2
- package/dist/{index-5fe6fb98.esm.js → index-915dd675.esm.js} +644 -50
- package/dist/{index-61237991.cjs.prod.js → index-a3846321.cjs.prod.js} +649 -49
- package/dist/{index-9860179f.cjs.dev.js → index-daa122af.cjs.dev.js} +649 -49
- package/dist/valbuild-core.cjs.dev.js +7 -1
- package/dist/valbuild-core.cjs.prod.js +7 -1
- package/dist/valbuild-core.esm.js +1 -1
- package/package.json +1 -1
- package/patch/dist/valbuild-core-patch.cjs.dev.js +1 -1
- package/patch/dist/valbuild-core-patch.cjs.prod.js +1 -1
- package/patch/dist/valbuild-core-patch.esm.js +2 -2
|
@@ -1962,7 +1962,7 @@ var union = function union(key) {
|
|
|
1962
1962
|
return new UnionSchema(key, objects);
|
|
1963
1963
|
};
|
|
1964
1964
|
|
|
1965
|
-
var RegEx = /^(https?:\/\/[^/]+)\/file\/p\/([^/]+)\/b\/([^/]+)\/v\/([^/]+)\/h\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
|
|
1965
|
+
var RegEx$1 = /^(https?:\/\/[^/]+)\/file\/p\/([^/]+)\/b\/([^/]+)\/v\/([^/]+)\/h\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
|
|
1966
1966
|
function splitRemoteRef(ref) {
|
|
1967
1967
|
if (ref[0] === "/") {
|
|
1968
1968
|
return {
|
|
@@ -1970,7 +1970,7 @@ function splitRemoteRef(ref) {
|
|
|
1970
1970
|
error: "Not a remote ref: " + ref
|
|
1971
1971
|
};
|
|
1972
1972
|
}
|
|
1973
|
-
var match = ref.match(RegEx);
|
|
1973
|
+
var match = ref.match(RegEx$1);
|
|
1974
1974
|
if (!match) {
|
|
1975
1975
|
return {
|
|
1976
1976
|
status: "error",
|
|
@@ -4368,6 +4368,94 @@ function _resolveJsonValues() {
|
|
|
4368
4368
|
return _resolveJsonValues.apply(this, arguments);
|
|
4369
4369
|
}
|
|
4370
4370
|
|
|
4371
|
+
/**
|
|
4372
|
+
* The string used as the `_type` discriminator of an {@link ExternalRecordSrc}.
|
|
4373
|
+
*/
|
|
4374
|
+
var EXTERNAL_VAL_EXTENSION_TAG = "external";
|
|
4375
|
+
|
|
4376
|
+
/**
|
|
4377
|
+
* Type-level-only slots. Declared here rather than reusing `PhantomType`
|
|
4378
|
+
* (`source/index.ts`) because three separate facts have to ride along, and that
|
|
4379
|
+
* helper carries one.
|
|
4380
|
+
*
|
|
4381
|
+
* None of them exist at runtime: `c.external()` produces `{ _type: "external" }`
|
|
4382
|
+
* and nothing else.
|
|
4383
|
+
*/
|
|
4384
|
+
|
|
4385
|
+
/**
|
|
4386
|
+
* The source of a record whose entries live behind an adapter — a database, an
|
|
4387
|
+
* HTTP API, a bucket — instead of in the module.
|
|
4388
|
+
*
|
|
4389
|
+
* This is what `c.external()` returns, and it is the counterpart of the
|
|
4390
|
+
* `c.json(() => import(...))` marker a `.jsonValues()` entry carries: a value
|
|
4391
|
+
* that says "the content is not here" without saying anything about what is.
|
|
4392
|
+
* The schema says *which* adapter (`.external("posts")`); this says *that* the
|
|
4393
|
+
* entries are elsewhere, which is what every source-walking consumer needs to
|
|
4394
|
+
* know without holding a schema.
|
|
4395
|
+
*
|
|
4396
|
+
* Three phantom parameters, each earning its place:
|
|
4397
|
+
*
|
|
4398
|
+
* - `T` — the item type. Without it `c.define` would return a module whose type
|
|
4399
|
+
* is "a marker", the item type would be gone, and an adapter could not be
|
|
4400
|
+
* typed from the schema at all.
|
|
4401
|
+
* - `L` — the label from `.external(label)`, so a binding can be checked against
|
|
4402
|
+
* the schema that declared it.
|
|
4403
|
+
* - `RO` — whether the schema said `.readonly()`, which decides whether the
|
|
4404
|
+
* adapter must implement writes or is forbidden from doing so.
|
|
4405
|
+
*
|
|
4406
|
+
* The defaults are the WIDEST instantiation on purpose: the bare name appears in
|
|
4407
|
+
* the `Source` and `SelectorSource` unions, and every narrower instantiation has
|
|
4408
|
+
* to be assignable to it. The `external()` factory below defaults the other way,
|
|
4409
|
+
* exactly as `JsonSource<T = unknown>` and `json<T = Json>()` do.
|
|
4410
|
+
*/
|
|
4411
|
+
|
|
4412
|
+
/**
|
|
4413
|
+
* The marker written as a module's source when its record is `.external()`.
|
|
4414
|
+
*
|
|
4415
|
+
* Takes no arguments: everything it carries is inferred from the schema it is
|
|
4416
|
+
* checked against in `c.define`. The assertion mirrors `json()` — the phantom
|
|
4417
|
+
* slots are symbol-keyed and have no runtime representation, so there is nothing
|
|
4418
|
+
* to construct for them.
|
|
4419
|
+
*/
|
|
4420
|
+
function external() {
|
|
4421
|
+
return _defineProperty({}, VAL_EXTENSION, EXTERNAL_VAL_EXTENSION_TAG);
|
|
4422
|
+
}
|
|
4423
|
+
function isExternal(obj) {
|
|
4424
|
+
return _typeof(obj) === "object" && obj !== null && VAL_EXTENSION in obj && obj[VAL_EXTENSION] === EXTERNAL_VAL_EXTENSION_TAG;
|
|
4425
|
+
}
|
|
4426
|
+
|
|
4427
|
+
/**
|
|
4428
|
+
* The item type an external record holds, read back off a module.
|
|
4429
|
+
*
|
|
4430
|
+
* `GenericSelector` is not imported here — that would be a cycle through
|
|
4431
|
+
* `../selector` — so this is written against the phantom slot directly and the
|
|
4432
|
+
* selector-shaped overloads live where the selector types do.
|
|
4433
|
+
*/
|
|
4434
|
+
|
|
4435
|
+
/** The label an external record was declared with. */
|
|
4436
|
+
|
|
4437
|
+
/** Whether the schema behind an external record said `.readonly()`. */
|
|
4438
|
+
|
|
4439
|
+
/**
|
|
4440
|
+
* The source of an external record as it may be WRITTEN.
|
|
4441
|
+
*
|
|
4442
|
+
* Either the marker, or entries inline in the `.val.ts`. Inline entries are
|
|
4443
|
+
* accepted by the type on purpose, for the same reason `.jsonValues()` accepts
|
|
4444
|
+
* them (see `JsonValuesRecordSrc`): pasting content straight into the module is
|
|
4445
|
+
* the natural first thing to write, and a type error there is a dead end — the
|
|
4446
|
+
* author cannot see what to write instead. Validation reports the inline entries
|
|
4447
|
+
* as an `external:upload` fix instead, so the mistake is repaired rather than
|
|
4448
|
+
* blocking authoring, and they are readable at runtime meanwhile.
|
|
4449
|
+
*/
|
|
4450
|
+
|
|
4451
|
+
/**
|
|
4452
|
+
* Is this module source an external record that still has entries written
|
|
4453
|
+
* inline? Used by validation to raise `external:upload`.
|
|
4454
|
+
*/
|
|
4455
|
+
function hasInlineExternalEntries(source) {
|
|
4456
|
+
return _typeof(source) === "object" && source !== null && !Array.isArray(source) && !isExternal(source) && Object.keys(source).length > 0;
|
|
4457
|
+
}
|
|
4458
|
+
|
|
4371
4459
|
/**
|
|
4372
4460
|
* The source type of a `.jsonValues()` record: every entry value is EITHER a
|
|
4373
4461
|
* lazily loaded {@link JsonSource} whose resolved content is the (loosened, see
|
|
@@ -4396,6 +4484,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4396
4484
|
var isJsonValues = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
|
|
4397
4485
|
var previewInput = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : null;
|
|
4398
4486
|
var renderInput = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : null;
|
|
4487
|
+
var externalLabel = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : null;
|
|
4399
4488
|
_classCallCheck(this, RecordSchema);
|
|
4400
4489
|
_this = _callSuper(this, RecordSchema);
|
|
4401
4490
|
_this.item = item;
|
|
@@ -4410,24 +4499,28 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4410
4499
|
_this.isJsonValues = isJsonValues;
|
|
4411
4500
|
_this.previewInput = previewInput;
|
|
4412
4501
|
_this.renderInput = renderInput;
|
|
4502
|
+
_this.externalLabel = externalLabel;
|
|
4413
4503
|
return _this;
|
|
4414
4504
|
}
|
|
4415
4505
|
_inherits(RecordSchema, _Schema);
|
|
4416
4506
|
return _createClass(RecordSchema, [{
|
|
4417
4507
|
key: "describe",
|
|
4418
4508
|
value: function describe(description) {
|
|
4419
|
-
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);
|
|
4509
|
+
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);
|
|
4420
4510
|
}
|
|
4421
4511
|
}, {
|
|
4422
4512
|
key: "validate",
|
|
4423
4513
|
value: function validate(validationFunction) {
|
|
4424
|
-
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);
|
|
4514
|
+
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);
|
|
4425
4515
|
}
|
|
4426
4516
|
}, {
|
|
4427
4517
|
key: "executeValidate",
|
|
4428
4518
|
value: function executeValidate(path, src) {
|
|
4429
4519
|
var _this2 = this;
|
|
4430
4520
|
var error = false;
|
|
4521
|
+
if (this.externalLabel !== null) {
|
|
4522
|
+
return this.validateExternal(path, src);
|
|
4523
|
+
}
|
|
4431
4524
|
var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
|
|
4432
4525
|
path: path
|
|
4433
4526
|
});
|
|
@@ -4764,31 +4857,42 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4764
4857
|
}, {
|
|
4765
4858
|
key: "nullable",
|
|
4766
4859
|
value: function nullable() {
|
|
4767
|
-
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);
|
|
4860
|
+
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);
|
|
4768
4861
|
}
|
|
4862
|
+
|
|
4863
|
+
/**
|
|
4864
|
+
* A record you can look at but not change.
|
|
4865
|
+
*
|
|
4866
|
+
* The flag rides in the TYPE as well as in the instance, so `.external()` can
|
|
4867
|
+
* freeze it into the source marker and the adapter's write methods become
|
|
4868
|
+
* required or forbidden on the strength of it. That is also why `.readonly()`
|
|
4869
|
+
* must come BEFORE `.external()`: afterwards the value is a `Schema`, and
|
|
4870
|
+
* there is no `.readonly()` left to call — which is the error the compiler
|
|
4871
|
+
* gives, and a clearer one than a runtime throw.
|
|
4872
|
+
*/
|
|
4769
4873
|
}, {
|
|
4770
4874
|
key: "readonly",
|
|
4771
4875
|
value: function readonly() {
|
|
4772
4876
|
var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
4773
|
-
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);
|
|
4877
|
+
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);
|
|
4774
4878
|
}
|
|
4775
4879
|
}, {
|
|
4776
4880
|
key: "hidden",
|
|
4777
4881
|
value: function hidden() {
|
|
4778
4882
|
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
4779
|
-
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);
|
|
4883
|
+
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);
|
|
4780
4884
|
}
|
|
4781
4885
|
}, {
|
|
4782
4886
|
key: "router",
|
|
4783
4887
|
value: function router(_router) {
|
|
4784
|
-
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);
|
|
4888
|
+
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);
|
|
4785
4889
|
}
|
|
4786
4890
|
}, {
|
|
4787
4891
|
key: "remote",
|
|
4788
4892
|
value: function remote() {
|
|
4789
4893
|
return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions ? _objectSpread2(_objectSpread2({}, this.mediaOptions), {}, {
|
|
4790
4894
|
remote: true
|
|
4791
|
-
}) : undefined, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput);
|
|
4895
|
+
}) : undefined, this.isReadonly, this.isHidden, this.description, this.isJsonValues, this.previewInput, this.renderInput, this.externalLabel);
|
|
4792
4896
|
}
|
|
4793
4897
|
|
|
4794
4898
|
/**
|
|
@@ -4830,7 +4934,84 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4830
4934
|
// Empty by construction: the guard above rejects any that were registered.
|
|
4831
4935
|
[], this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, true,
|
|
4832
4936
|
// Null by construction: the guard above rejects any that was declared.
|
|
4833
|
-
null, this.renderInput);
|
|
4937
|
+
null, this.renderInput, this.externalLabel);
|
|
4938
|
+
}
|
|
4939
|
+
|
|
4940
|
+
/**
|
|
4941
|
+
* Store this record's entries behind an adapter — a database, an HTTP API, a
|
|
4942
|
+
* bucket — instead of in the module.
|
|
4943
|
+
*
|
|
4944
|
+
* Available on every record-derived schema, which is `s.record()`,
|
|
4945
|
+
* `s.router()`, `s.images()` and `s.files()` alike: a router is a
|
|
4946
|
+
* `RecordSchema` with a `ValRouter`, a gallery one with media options, so all
|
|
4947
|
+
* four get external storage from this one method.
|
|
4948
|
+
*
|
|
4949
|
+
* `label` does not address the binding — the registry is keyed by module, and
|
|
4950
|
+
* so is the wire protocol. It exists so a reader of the schema can see what
|
|
4951
|
+
* backs it, and it is checked against the binding that claims it, so the two
|
|
4952
|
+
* cannot drift.
|
|
4953
|
+
*
|
|
4954
|
+
* Only supported on a module's ROOT record, exactly as `.jsonValues()` is: a
|
|
4955
|
+
* nested external record would leave a hole in the middle of a module's
|
|
4956
|
+
* source, and the Studio, patching and validation all assume a module's
|
|
4957
|
+
* source is complete apart from its entries.
|
|
4958
|
+
*/
|
|
4959
|
+
}, {
|
|
4960
|
+
key: "external",
|
|
4961
|
+
value: function external(label) {
|
|
4962
|
+
if (this.isJsonValues) {
|
|
4963
|
+
throw new Error(".external() cannot be combined with .jsonValues(): entries live in one place or the other, not both.");
|
|
4964
|
+
}
|
|
4965
|
+
if (!label) {
|
|
4966
|
+
throw new Error('.external() requires a label, e.g. .external("posts")');
|
|
4967
|
+
}
|
|
4968
|
+
return new RecordSchema(this.item, this.opt,
|
|
4969
|
+
// Empty by construction: a validator declared before `.external()` is
|
|
4970
|
+
// typed against the un-external source shape and cannot be carried over.
|
|
4971
|
+
[], this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, this.isJsonValues, null, this.renderInput, label);
|
|
4972
|
+
}
|
|
4973
|
+
|
|
4974
|
+
/**
|
|
4975
|
+
* An external record's source is either the `c.external()` marker or entries
|
|
4976
|
+
* still written inline in the `.val.ts`.
|
|
4977
|
+
*
|
|
4978
|
+
* Inline entries are NOT a type error (see `ExternalRecordWritableSrc`), so
|
|
4979
|
+
* this is where they surface: as an `external:upload` fix, per key, the way
|
|
4980
|
+
* `.jsonValues()` reports an un-extracted entry. Reporting per key rather than
|
|
4981
|
+
* once for the record is what lets the fix be applied to one entry, and what
|
|
4982
|
+
* puts the error at a path the editor can navigate to.
|
|
4983
|
+
*/
|
|
4984
|
+
}, {
|
|
4985
|
+
key: "validateExternal",
|
|
4986
|
+
value: function validateExternal(path, src) {
|
|
4987
|
+
if (this.opt && (src === null || src === undefined)) {
|
|
4988
|
+
return false;
|
|
4989
|
+
}
|
|
4990
|
+
if (src === null || _typeof(src) !== "object" || Array.isArray(src)) {
|
|
4991
|
+
return _defineProperty({}, path, [{
|
|
4992
|
+
message: "Expected the c.external() marker or inline entries, got '".concat(src === null ? "null" : Array.isArray(src) ? "array" : _typeof(src), "'"),
|
|
4993
|
+
value: src,
|
|
4994
|
+
schemaError: true
|
|
4995
|
+
}]);
|
|
4996
|
+
}
|
|
4997
|
+
if (isExternal(src)) {
|
|
4998
|
+
// The marker: the entries are the adapter's, and there is nothing here to
|
|
4999
|
+
// check. Their content is validated as it is read.
|
|
5000
|
+
return false;
|
|
5001
|
+
}
|
|
5002
|
+
var error = false;
|
|
5003
|
+
for (var _i = 0, _Object$keys = Object.keys(src); _i < _Object$keys.length; _i++) {
|
|
5004
|
+
var _key = _Object$keys[_i];
|
|
5005
|
+
var subPath = createValPathOfItem(path, _key);
|
|
5006
|
+
if (!subPath) {
|
|
5007
|
+
continue;
|
|
5008
|
+
}
|
|
5009
|
+
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]);
|
|
5010
|
+
var errors = error;
|
|
5011
|
+
var last = errors[subPath][errors[subPath].length - 1];
|
|
5012
|
+
last.fixes = ["external:upload"];
|
|
5013
|
+
}
|
|
5014
|
+
return error;
|
|
4834
5015
|
}
|
|
4835
5016
|
}, {
|
|
4836
5017
|
key: "getRouterValidations",
|
|
@@ -4884,7 +5065,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4884
5065
|
}, {
|
|
4885
5066
|
key: "executeSerialize",
|
|
4886
5067
|
value: function executeSerialize() {
|
|
4887
|
-
var _this$renderInput, _this$keySchema, _this$currentRouter, _this$customValidateF;
|
|
5068
|
+
var _this$renderInput, _this$keySchema, _this$currentRouter, _this$customValidateF, _this$externalLabel;
|
|
4888
5069
|
var result = {
|
|
4889
5070
|
type: "record",
|
|
4890
5071
|
render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
|
|
@@ -4895,6 +5076,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4895
5076
|
router: (_this$currentRouter = this.currentRouter) === null || _this$currentRouter === void 0 ? void 0 : _this$currentRouter.getRouterId(),
|
|
4896
5077
|
customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
|
|
4897
5078
|
jsonValues: this.isJsonValues ? true : undefined,
|
|
5079
|
+
external: (_this$externalLabel = this.externalLabel) !== null && _this$externalLabel !== void 0 ? _this$externalLabel : undefined,
|
|
4898
5080
|
readonly: this.isReadonly,
|
|
4899
5081
|
hidden: this.isHidden,
|
|
4900
5082
|
description: this.description
|
|
@@ -4932,8 +5114,12 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4932
5114
|
if (src === null) {
|
|
4933
5115
|
return res;
|
|
4934
5116
|
}
|
|
4935
|
-
|
|
4936
|
-
|
|
5117
|
+
if (isExternal(src)) {
|
|
5118
|
+
// The entries are the adapter's; there is nothing here to preview.
|
|
5119
|
+
return res;
|
|
5120
|
+
}
|
|
5121
|
+
for (var _key2 in src) {
|
|
5122
|
+
var itemSrc = src[_key2];
|
|
4937
5123
|
if (itemSrc === null || itemSrc === undefined) {
|
|
4938
5124
|
continue;
|
|
4939
5125
|
}
|
|
@@ -4944,14 +5130,14 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4944
5130
|
// keys, and the caller shows a placeholder for the rest.
|
|
4945
5131
|
continue;
|
|
4946
5132
|
}
|
|
4947
|
-
var subPath = unsafeCreateSourcePath(sourcePath,
|
|
5133
|
+
var subPath = unsafeCreateSourcePath(sourcePath, _key2);
|
|
4948
5134
|
if (scope !== undefined && !scope.wantsUnder(subPath)) {
|
|
4949
5135
|
continue;
|
|
4950
5136
|
}
|
|
4951
5137
|
var itemResult = this.item["executePreview"](subPath, itemSrc, scope);
|
|
4952
5138
|
for (var keyS in itemResult) {
|
|
4953
|
-
var
|
|
4954
|
-
res[
|
|
5139
|
+
var _key3 = keyS;
|
|
5140
|
+
res[_key3] = itemResult[_key3];
|
|
4955
5141
|
}
|
|
4956
5142
|
}
|
|
4957
5143
|
// The entries preview comes from the ITEM schema's own `preview` — the
|
|
@@ -4962,9 +5148,9 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4962
5148
|
// is being shown, only the wanted entries when it is not.
|
|
4963
5149
|
var window = scope !== undefined && !scope.wants(sourcePath) ? scope : null;
|
|
4964
5150
|
var items = [];
|
|
4965
|
-
for (var
|
|
4966
|
-
var _Object$entries$_i = _slicedToArray(_Object$entries[
|
|
4967
|
-
|
|
5151
|
+
for (var _i2 = 0, _Object$entries = Object.entries(src); _i2 < _Object$entries.length; _i2++) {
|
|
5152
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i2], 2),
|
|
5153
|
+
_key4 = _Object$entries$_i[0],
|
|
4968
5154
|
val = _Object$entries$_i[1];
|
|
4969
5155
|
if (isJson(val)) {
|
|
4970
5156
|
continue; // as above: nothing to select from an un-loaded entry
|
|
@@ -4972,7 +5158,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4972
5158
|
if (val === null || val === undefined) {
|
|
4973
5159
|
continue;
|
|
4974
5160
|
}
|
|
4975
|
-
if (window !== null && !window.wantsUnder(unsafeCreateSourcePath(sourcePath,
|
|
5161
|
+
if (window !== null && !window.wantsUnder(unsafeCreateSourcePath(sourcePath, _key4))) {
|
|
4976
5162
|
continue;
|
|
4977
5163
|
}
|
|
4978
5164
|
// Per KEY, not per record: the closure is user code, and one entry whose
|
|
@@ -4984,14 +5170,14 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4984
5170
|
var title = _item.title,
|
|
4985
5171
|
subtitle = _item.subtitle,
|
|
4986
5172
|
image = _item.image;
|
|
4987
|
-
items.push([
|
|
5173
|
+
items.push([_key4, {
|
|
4988
5174
|
title: title,
|
|
4989
5175
|
subtitle: subtitle,
|
|
4990
5176
|
image: image
|
|
4991
5177
|
}]);
|
|
4992
5178
|
}
|
|
4993
5179
|
} catch (e) {
|
|
4994
|
-
res[unsafeCreateSourcePath(sourcePath,
|
|
5180
|
+
res[unsafeCreateSourcePath(sourcePath, _key4)] = {
|
|
4995
5181
|
status: "error",
|
|
4996
5182
|
message: e instanceof Error ? e.message : "Unknown error"
|
|
4997
5183
|
};
|
|
@@ -5032,7 +5218,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5032
5218
|
}, {
|
|
5033
5219
|
key: "preview",
|
|
5034
5220
|
value: function preview(select) {
|
|
5035
|
-
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);
|
|
5221
|
+
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);
|
|
5036
5222
|
}
|
|
5037
5223
|
|
|
5038
5224
|
/**
|
|
@@ -5045,7 +5231,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5045
5231
|
}, {
|
|
5046
5232
|
key: "render",
|
|
5047
5233
|
value: function render(input) {
|
|
5048
|
-
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);
|
|
5234
|
+
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);
|
|
5049
5235
|
}
|
|
5050
5236
|
}]);
|
|
5051
5237
|
}(Schema);
|
|
@@ -5546,6 +5732,22 @@ function settings() {
|
|
|
5546
5732
|
});
|
|
5547
5733
|
}
|
|
5548
5734
|
|
|
5735
|
+
/**
|
|
5736
|
+
* What may be WRITTEN as an external record's source, on top of the marker.
|
|
5737
|
+
*
|
|
5738
|
+
* Entries inline in the `.val.ts` are accepted on purpose — the same call
|
|
5739
|
+
* `.jsonValues()` makes for the same reason: pasting content straight into the
|
|
5740
|
+
* module is the natural first thing to write, and a type error there is a dead
|
|
5741
|
+
* end, because the author cannot see what to write instead. Validation reports
|
|
5742
|
+
* them as an `external:upload` fix, and they are readable at runtime meanwhile.
|
|
5743
|
+
*
|
|
5744
|
+
* Widened HERE rather than in the schema's own source type so that the MODULE
|
|
5745
|
+
* stays typed on the marker alone. An adapter is bound to a module, and a module
|
|
5746
|
+
* whose type were "marker or plain record" would be indistinguishable from an
|
|
5747
|
+
* ordinary record — which would let `entry()` accept a module that is not
|
|
5748
|
+
* external at all.
|
|
5749
|
+
*/
|
|
5750
|
+
|
|
5549
5751
|
function define(id,
|
|
5550
5752
|
// TODO: `/${string}`
|
|
5551
5753
|
schema, source) {
|
|
@@ -6953,6 +7155,8 @@ function file(options) {
|
|
|
6953
7155
|
/**
|
|
6954
7156
|
* Define a collection of files.
|
|
6955
7157
|
*
|
|
7158
|
+
* Remote is off by default: call `.remote()` on the result to allow remote files.
|
|
7159
|
+
*
|
|
6956
7160
|
* @example
|
|
6957
7161
|
* ```typescript
|
|
6958
7162
|
* const schema = s.files({
|
|
@@ -6967,7 +7171,6 @@ function file(options) {
|
|
|
6967
7171
|
* ```
|
|
6968
7172
|
*/
|
|
6969
7173
|
var files = function files(options) {
|
|
6970
|
-
var _options$remote;
|
|
6971
7174
|
var directory = options.directory;
|
|
6972
7175
|
var itemSchema = new ObjectSchema({
|
|
6973
7176
|
mimeType: new StringSchema({}, false)
|
|
@@ -6976,7 +7179,7 @@ var files = function files(options) {
|
|
|
6976
7179
|
type: "files",
|
|
6977
7180
|
accept: options.accept,
|
|
6978
7181
|
directory: directory,
|
|
6979
|
-
remote:
|
|
7182
|
+
remote: false
|
|
6980
7183
|
});
|
|
6981
7184
|
};
|
|
6982
7185
|
|
|
@@ -8344,7 +8547,7 @@ function router(router, keyOrItem, maybeItem) {
|
|
|
8344
8547
|
*
|
|
8345
8548
|
* `directory` is required — it decides where uploads land, so it is not something
|
|
8346
8549
|
* to be inferred. The rest defaults: any image type (`"image/*"`), nullable alt
|
|
8347
|
-
* text, remote disabled.
|
|
8550
|
+
* text, remote disabled. Call `.remote()` on the result to allow remote images.
|
|
8348
8551
|
*
|
|
8349
8552
|
* @example
|
|
8350
8553
|
* ```typescript
|
|
@@ -8364,7 +8567,7 @@ function router(router, keyOrItem, maybeItem) {
|
|
|
8364
8567
|
* ```
|
|
8365
8568
|
*/
|
|
8366
8569
|
var images = function images(options) {
|
|
8367
|
-
var _options$alt, _options$accept
|
|
8570
|
+
var _options$alt, _options$accept;
|
|
8368
8571
|
var directory = options.directory;
|
|
8369
8572
|
var altSchema = (_options$alt = options.alt) !== null && _options$alt !== void 0 ? _options$alt : string().nullable();
|
|
8370
8573
|
var itemSchema = new ObjectSchema({
|
|
@@ -8377,7 +8580,7 @@ var images = function images(options) {
|
|
|
8377
8580
|
type: "images",
|
|
8378
8581
|
accept: (_options$accept = options.accept) !== null && _options$accept !== void 0 ? _options$accept : "image/*",
|
|
8379
8582
|
directory: directory,
|
|
8380
|
-
remote:
|
|
8583
|
+
remote: false,
|
|
8381
8584
|
altSchema: altSchema,
|
|
8382
8585
|
encode: options.encode
|
|
8383
8586
|
});
|
|
@@ -8455,7 +8658,8 @@ var initVal = function initVal(config) {
|
|
|
8455
8658
|
},
|
|
8456
8659
|
c: {
|
|
8457
8660
|
define: define,
|
|
8458
|
-
json: json
|
|
8661
|
+
json: json,
|
|
8662
|
+
external: external
|
|
8459
8663
|
},
|
|
8460
8664
|
s: s,
|
|
8461
8665
|
config: config
|
|
@@ -9252,9 +9456,10 @@ function _extractValModules() {
|
|
|
9252
9456
|
* The one answer to that question. There used to be two — `hasRemoteFileSchema`
|
|
9253
9457
|
* in the server, gating whether `/save` demands remote credentials, and
|
|
9254
9458
|
* `findRequiredRemoteFiles` in the Studio, gating the `/remote/settings` fetch —
|
|
9255
|
-
* and they disagreed about `s.images({
|
|
9256
|
-
* remote media record, the server's did not, because a media
|
|
9257
|
-
* serializes as a `record` of metadata rather than as an image
|
|
9459
|
+
* and they disagreed about `s.images({ ... }).remote()`: the Studio's version
|
|
9460
|
+
* counted a remote media record, the server's did not, because a media
|
|
9461
|
+
* collection serializes as a `record` of metadata rather than as an image
|
|
9462
|
+
* schema.
|
|
9258
9463
|
*
|
|
9259
9464
|
* The server's answer was the wrong one, and silently so. With it false,
|
|
9260
9465
|
* `/save` runs `saveOrUploadFiles` in `skip-remote` mode, and that mode does not
|
|
@@ -9347,6 +9552,85 @@ function hasRemoteFileSchema(schema) {
|
|
|
9347
9552
|
}
|
|
9348
9553
|
}
|
|
9349
9554
|
|
|
9555
|
+
/**
|
|
9556
|
+
* Does this schema hold any media at all — remote or not?
|
|
9557
|
+
*
|
|
9558
|
+
* The sibling of {@link hasRemoteFileSchema}, and the same walk minus the
|
|
9559
|
+
* `remote` predicate. It answers the question an external record has to ask
|
|
9560
|
+
* before it will accept a binding: an item schema containing media needs a
|
|
9561
|
+
* `putFile`/`getFile` pair, and without one that is a schema error.
|
|
9562
|
+
*
|
|
9563
|
+
* It is a walk over the SERIALIZED schema for the reasons given above, and for
|
|
9564
|
+
* one more that is specific to this question: the two cases most likely to be
|
|
9565
|
+
* missed are invisible to a value type. A media collection (`s.images()` /
|
|
9566
|
+
* `s.files()`) serializes as a record of metadata with no image schema inside
|
|
9567
|
+
* it, and a richtext inline image lives in a constructor argument. A check
|
|
9568
|
+
* written against the item TYPE would silently pass both — and the gallery case
|
|
9569
|
+
* already has a data-loss incident attached to it (see above).
|
|
9570
|
+
*/
|
|
9571
|
+
function hasMediaSchema(schema) {
|
|
9572
|
+
if (schema.type === "file" || schema.type === "image") {
|
|
9573
|
+
return true;
|
|
9574
|
+
} else if (schema.type === "richtext") {
|
|
9575
|
+
var _schema$options2;
|
|
9576
|
+
// `img` is `boolean | SerializedImageSchema`: `true` means inline images are
|
|
9577
|
+
// allowed with the DEFAULT image schema, and is just as much media as a
|
|
9578
|
+
// spelled-out one. `hasRemoteFileSchema` tests only for an object because a
|
|
9579
|
+
// default image is not remote — a different question with a different
|
|
9580
|
+
// answer, which is why these two walks are separate functions.
|
|
9581
|
+
if ((_schema$options2 = schema.options) !== null && _schema$options2 !== void 0 && _schema$options2.img) {
|
|
9582
|
+
return true;
|
|
9583
|
+
}
|
|
9584
|
+
return false;
|
|
9585
|
+
} else if (schema.type === "array") {
|
|
9586
|
+
return hasMediaSchema(schema.item);
|
|
9587
|
+
} else if (schema.type === "record") {
|
|
9588
|
+
// A media collection names its file by the record's KEY, so there is no
|
|
9589
|
+
// image schema inside to find: `mediaType` is where the answer is written.
|
|
9590
|
+
if (schema.mediaType) {
|
|
9591
|
+
return true;
|
|
9592
|
+
}
|
|
9593
|
+
return hasMediaSchema(schema.item);
|
|
9594
|
+
} else if (schema.type === "object") {
|
|
9595
|
+
for (var key in schema.items) {
|
|
9596
|
+
if (hasMediaSchema(schema.items[key])) {
|
|
9597
|
+
return true;
|
|
9598
|
+
}
|
|
9599
|
+
}
|
|
9600
|
+
return false;
|
|
9601
|
+
} else if (schema.type === "union") {
|
|
9602
|
+
var unionObjectSchema = typeof schema.key === "string" ? schema : undefined;
|
|
9603
|
+
if (unionObjectSchema) {
|
|
9604
|
+
var _iterator2 = _createForOfIteratorHelper(unionObjectSchema.items),
|
|
9605
|
+
_step2;
|
|
9606
|
+
try {
|
|
9607
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
9608
|
+
var item = _step2.value;
|
|
9609
|
+
if (hasMediaSchema(item)) {
|
|
9610
|
+
return true;
|
|
9611
|
+
}
|
|
9612
|
+
}
|
|
9613
|
+
} catch (err) {
|
|
9614
|
+
_iterator2.e(err);
|
|
9615
|
+
} finally {
|
|
9616
|
+
_iterator2.f();
|
|
9617
|
+
}
|
|
9618
|
+
}
|
|
9619
|
+
// A string union's items are literals, so there is nothing to look inside.
|
|
9620
|
+
return false;
|
|
9621
|
+
} 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" ||
|
|
9622
|
+
// A settings module holds the assistant's configuration, not content, and
|
|
9623
|
+
// nothing in it is media.
|
|
9624
|
+
schema.type === "settings") {
|
|
9625
|
+
return false;
|
|
9626
|
+
} else {
|
|
9627
|
+
// Same contract as above: adding a schema type without teaching this
|
|
9628
|
+
// function about it must not compile.
|
|
9629
|
+
var exhaustiveCheck = schema;
|
|
9630
|
+
throw new Error("Unexpected schema: ".concat(JSON.stringify(exhaustiveCheck)));
|
|
9631
|
+
}
|
|
9632
|
+
}
|
|
9633
|
+
|
|
9350
9634
|
var DEFAULT_VAL_REMOTE_HOST = "https://remote.val.build";
|
|
9351
9635
|
|
|
9352
9636
|
var PatchError = /*#__PURE__*/_createClass(function PatchError(message) {
|
|
@@ -9491,6 +9775,79 @@ function mediaPathOf(value) {
|
|
|
9491
9775
|
return typeof path === "string" ? path : null;
|
|
9492
9776
|
}
|
|
9493
9777
|
|
|
9778
|
+
/**
|
|
9779
|
+
* The reference stored for a file whose bytes live behind an external adapter.
|
|
9780
|
+
*
|
|
9781
|
+
* Deliberately the same shape of idea as a remote ref (`remote/splitRemoteRef`):
|
|
9782
|
+
* a URL-ish string that **ends with the file's virtual path**, so the file's
|
|
9783
|
+
* logical identity survives wherever its bytes happen to be.
|
|
9784
|
+
*
|
|
9785
|
+
* /api/val/external/documents/f/{fileHash}/p/public/val/documents/report_a1b2c.pdf
|
|
9786
|
+
* \__________________________/ \________/ \_______________________________/
|
|
9787
|
+
* route + label content the path a LOCAL file
|
|
9788
|
+
* address would have had
|
|
9789
|
+
*
|
|
9790
|
+
* Three things follow from that shape, and each is load-bearing:
|
|
9791
|
+
*
|
|
9792
|
+
* - **`media.ts` needs no change.** `isRemote` is `!path.startsWith("/public")`,
|
|
9793
|
+
* and this does not, so `Internal.mediaUrl` returns the ref as-is and Val's
|
|
9794
|
+
* route serves it. The media rule that has been got wrong repeatedly is left
|
|
9795
|
+
* exactly alone.
|
|
9796
|
+
* - **Moving between storage modes is mechanical.** External → local reads the
|
|
9797
|
+
* `public/…` suffix back out, fetches the bytes and writes them there; local →
|
|
9798
|
+
* external uploads the file already at that path. Nothing is renamed.
|
|
9799
|
+
* - **The filename is Val's, not the adapter's**, produced by the same
|
|
9800
|
+
* `createFilename` a local or remote file uses — so the same bytes get the
|
|
9801
|
+
* same name under all three storage modes.
|
|
9802
|
+
*/
|
|
9803
|
+
|
|
9804
|
+
var RegEx = /^\/api\/val\/external\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
|
|
9805
|
+
function createExternalFileRef(_ref) {
|
|
9806
|
+
var label = _ref.label,
|
|
9807
|
+
fileHash = _ref.fileHash,
|
|
9808
|
+
filePath = _ref.filePath;
|
|
9809
|
+
var withoutLeadingSlash = filePath.startsWith("/") ? filePath.slice(1) : filePath;
|
|
9810
|
+
if (!withoutLeadingSlash.startsWith("public/")) {
|
|
9811
|
+
throw new Error("External file paths must be under '/public', got: '".concat(filePath, "'"));
|
|
9812
|
+
}
|
|
9813
|
+
return "/api/val/external/".concat(label, "/f/").concat(fileHash, "/p/").concat(withoutLeadingSlash);
|
|
9814
|
+
}
|
|
9815
|
+
function splitExternalFileRef(ref) {
|
|
9816
|
+
var match = ref.match(RegEx);
|
|
9817
|
+
if (!match) {
|
|
9818
|
+
return {
|
|
9819
|
+
status: "error",
|
|
9820
|
+
error: "Not an external file ref: " + ref
|
|
9821
|
+
};
|
|
9822
|
+
}
|
|
9823
|
+
var filePath = match[3];
|
|
9824
|
+
if (!filePath.startsWith("public/")) {
|
|
9825
|
+
return {
|
|
9826
|
+
status: "error",
|
|
9827
|
+
error: "Invalid external file ref: " + ref
|
|
9828
|
+
};
|
|
9829
|
+
}
|
|
9830
|
+
// Traversal check, for the same reason `splitRemoteRef` has one: this path is
|
|
9831
|
+
// used to read and write files.
|
|
9832
|
+
if (filePath.split("/").some(function (segment) {
|
|
9833
|
+
return segment === "." || segment === "..";
|
|
9834
|
+
})) {
|
|
9835
|
+
return {
|
|
9836
|
+
status: "error",
|
|
9837
|
+
error: "Invalid external file ref: " + ref
|
|
9838
|
+
};
|
|
9839
|
+
}
|
|
9840
|
+
return {
|
|
9841
|
+
status: "success",
|
|
9842
|
+
label: match[1],
|
|
9843
|
+
fileHash: match[2],
|
|
9844
|
+
filePath: filePath
|
|
9845
|
+
};
|
|
9846
|
+
}
|
|
9847
|
+
function isExternalFileRef(ref) {
|
|
9848
|
+
return RegEx.test(ref);
|
|
9849
|
+
}
|
|
9850
|
+
|
|
9494
9851
|
// NOTE: the segments must match the ref built by createRemoteRef below and the RegEx in splitRemoteRef.
|
|
9495
9852
|
|
|
9496
9853
|
function createRemoteRef(remoteHost, _ref) {
|
|
@@ -9551,7 +9908,7 @@ function deserializeSchema(serialized) {
|
|
|
9551
9908
|
return schema;
|
|
9552
9909
|
}
|
|
9553
9910
|
function deserializeSchemaImpl(serialized) {
|
|
9554
|
-
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;
|
|
9911
|
+
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;
|
|
9555
9912
|
switch (serialized.type) {
|
|
9556
9913
|
case "string":
|
|
9557
9914
|
return new StringSchema(_objectSpread2(_objectSpread2({}, serialized.options), {}, {
|
|
@@ -9612,7 +9969,10 @@ function deserializeSchemaImpl(serialized) {
|
|
|
9612
9969
|
altSchema: serialized.alt ? deserializeSchema(serialized.alt) : undefined
|
|
9613
9970
|
} : undefined, false, false, serialized.description, (_serialized$jsonValue = serialized.jsonValues) !== null && _serialized$jsonValue !== void 0 ? _serialized$jsonValue : false,
|
|
9614
9971
|
// The preview closure cannot survive serialization; the render can.
|
|
9615
|
-
null, (_serialized$render9 = serialized.render) !== null && _serialized$render9 !== void 0 ? _serialized$render9 : null
|
|
9972
|
+
null, (_serialized$render9 = serialized.render) !== null && _serialized$render9 !== void 0 ? _serialized$render9 : null, // The external label is static data, so it survives serialization and
|
|
9973
|
+
// must be carried back: a deserialized schema that forgot it would walk
|
|
9974
|
+
// an external record as if its entries were local.
|
|
9975
|
+
(_serialized$external = serialized.external) !== null && _serialized$external !== void 0 ? _serialized$external : null);
|
|
9616
9976
|
case "keyOf":
|
|
9617
9977
|
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);
|
|
9618
9978
|
case "route":
|
|
@@ -10089,23 +10449,190 @@ function parseNextJsRoutePattern(moduleFilePath) {
|
|
|
10089
10449
|
return [];
|
|
10090
10450
|
}
|
|
10091
10451
|
|
|
10452
|
+
/**
|
|
10453
|
+
* Parse a TanStack Router route pattern out of a Val module file path.
|
|
10454
|
+
*
|
|
10455
|
+
* TanStack Router's file conventions are not Next's, so this is a different
|
|
10456
|
+
* parser rather than a flag on the one above. A Val module for a route lives
|
|
10457
|
+
* beside the route file and is named the same way — `routes/posts.$postId.tsx`
|
|
10458
|
+
* is served content by `routes/posts.$postId.val.ts` — so the pattern is the
|
|
10459
|
+
* file path with the conventions applied:
|
|
10460
|
+
*
|
|
10461
|
+
* - `.` and `/` both separate segments (`posts.$postId.val.ts` and
|
|
10462
|
+
* `posts/$postId.val.ts` are the same route)
|
|
10463
|
+
* - `$param` is a dynamic segment, `$` on its own is a splat
|
|
10464
|
+
* - `index` is the directory's own route and contributes no segment
|
|
10465
|
+
* - `route` is a layout for the directory, likewise
|
|
10466
|
+
* - `(group)` folders and `_pathless` layout segments are not in the URL
|
|
10467
|
+
* - a trailing `_` on a segment opts out of nesting and is not in the URL
|
|
10468
|
+
*
|
|
10469
|
+
* The result is expressed in the SAME vocabulary the Next parser uses
|
|
10470
|
+
* (`[param]`, `[...param]`), because everything downstream — validation, the
|
|
10471
|
+
* sitemap, the key inputs in the Studio — is written against that vocabulary
|
|
10472
|
+
* and there is no reason for two.
|
|
10473
|
+
*
|
|
10474
|
+
* - /src/routes/posts.$postId.val.ts -> ["posts", "[postId]"]
|
|
10475
|
+
* - /routes/posts/$postId.val.ts -> ["posts", "[postId]"]
|
|
10476
|
+
* - /src/routes/index.val.ts -> []
|
|
10477
|
+
* - /src/routes/files.$.val.ts -> ["files", "[..._splat]"]
|
|
10478
|
+
* - /src/routes/(app)/_layout.about.val.ts -> ["about"]
|
|
10479
|
+
*/
|
|
10480
|
+
function parseTanStackRoutePattern(moduleFilePath) {
|
|
10481
|
+
var segments = tanStackRouteSegments(moduleFilePath);
|
|
10482
|
+
if (segments === null) {
|
|
10483
|
+
return [];
|
|
10484
|
+
}
|
|
10485
|
+
return segments;
|
|
10486
|
+
}
|
|
10487
|
+
|
|
10488
|
+
/**
|
|
10489
|
+
* The segments, or `null` when the path is not a TanStack route module at all.
|
|
10490
|
+
*
|
|
10491
|
+
* Distinct from `parseTanStackRoutePattern`'s empty array, which is a real
|
|
10492
|
+
* answer: the root route `/` has no segments.
|
|
10493
|
+
*/
|
|
10494
|
+
function tanStackRouteSegments(moduleFilePath) {
|
|
10495
|
+
if (!moduleFilePath || typeof moduleFilePath !== "string") {
|
|
10496
|
+
return null;
|
|
10497
|
+
}
|
|
10498
|
+
var match = moduleFilePath.match(/^(?:\/src)?\/routes\/(.+)\.val\.[tj]sx?$/);
|
|
10499
|
+
if (!match) {
|
|
10500
|
+
return null;
|
|
10501
|
+
}
|
|
10502
|
+
return tanStackSegmentsOfRoutePath(match[1]);
|
|
10503
|
+
}
|
|
10504
|
+
|
|
10505
|
+
/**
|
|
10506
|
+
* The URL segments of a TanStack route path, given relative to `routes/`.
|
|
10507
|
+
*
|
|
10508
|
+
* Exported because the Studio derives the same pattern from the same file path
|
|
10509
|
+
* and must not disagree with validation about what a route is.
|
|
10510
|
+
*/
|
|
10511
|
+
function tanStackSegmentsOfRoutePath(routePath) {
|
|
10512
|
+
// `.` is a separator exactly like `/`, so flatten both before looking at any
|
|
10513
|
+
// segment: `posts/$postId.edit` and `posts.$postId.edit` are one route.
|
|
10514
|
+
var rawSegments = routePath.split("/").flatMap(function (part) {
|
|
10515
|
+
return part.split(".");
|
|
10516
|
+
}).filter(function (part) {
|
|
10517
|
+
return part !== "";
|
|
10518
|
+
});
|
|
10519
|
+
var segments = [];
|
|
10520
|
+
var _iterator3 = _createForOfIteratorHelper(rawSegments),
|
|
10521
|
+
_step3;
|
|
10522
|
+
try {
|
|
10523
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
10524
|
+
var rawSegment = _step3.value;
|
|
10525
|
+
// A route group: a folder that organises files without appearing in the URL.
|
|
10526
|
+
if (rawSegment.startsWith("(") && rawSegment.endsWith(")")) {
|
|
10527
|
+
continue;
|
|
10528
|
+
}
|
|
10529
|
+
// A pathless layout route. `_layout` nests its children without adding a
|
|
10530
|
+
// segment; `index`/`route` are the directory's own route and its layout.
|
|
10531
|
+
if (rawSegment.startsWith("_")) {
|
|
10532
|
+
continue;
|
|
10533
|
+
}
|
|
10534
|
+
if (rawSegment === "index" || rawSegment === "route") {
|
|
10535
|
+
continue;
|
|
10536
|
+
}
|
|
10537
|
+
// A trailing `_` opts the segment out of layout nesting; the URL keeps the
|
|
10538
|
+
// name without it.
|
|
10539
|
+
var segment = rawSegment.endsWith("_") ? rawSegment.slice(0, -1) : rawSegment;
|
|
10540
|
+
if (segment === "$") {
|
|
10541
|
+
// A splat. Named `_splat` because that is the param name TanStack gives
|
|
10542
|
+
// it, so `useValRoute(pageVal, params)` can be handed the route's own
|
|
10543
|
+
// params object unchanged.
|
|
10544
|
+
segments.push("[..._splat]");
|
|
10545
|
+
continue;
|
|
10546
|
+
}
|
|
10547
|
+
if (segment.startsWith("$")) {
|
|
10548
|
+
segments.push("[".concat(segment.slice(1), "]"));
|
|
10549
|
+
continue;
|
|
10550
|
+
}
|
|
10551
|
+
segments.push(segment);
|
|
10552
|
+
}
|
|
10553
|
+
} catch (err) {
|
|
10554
|
+
_iterator3.e(err);
|
|
10555
|
+
} finally {
|
|
10556
|
+
_iterator3.f();
|
|
10557
|
+
}
|
|
10558
|
+
return segments;
|
|
10559
|
+
}
|
|
10560
|
+
|
|
10561
|
+
/**
|
|
10562
|
+
* The router for a TanStack Router (and TanStack Start) app.
|
|
10563
|
+
*
|
|
10564
|
+
* Like `nextAppRouter` this does not belong in core — it is here for the same
|
|
10565
|
+
* reason that one is: the serialized schema carries only a router id, so the
|
|
10566
|
+
* thing that turns an id back into a validator has to be somewhere every
|
|
10567
|
+
* consumer can reach.
|
|
10568
|
+
*/
|
|
10569
|
+
var tanstackRouter = {
|
|
10570
|
+
getRouterId: function getRouterId() {
|
|
10571
|
+
return "tanstack-router";
|
|
10572
|
+
},
|
|
10573
|
+
validate: function validate(moduleFilePath, urlPaths) {
|
|
10574
|
+
var routePattern = parseTanStackRoutePattern(moduleFilePath);
|
|
10575
|
+
var errors = [];
|
|
10576
|
+
var _iterator4 = _createForOfIteratorHelper(urlPaths),
|
|
10577
|
+
_step4;
|
|
10578
|
+
try {
|
|
10579
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
10580
|
+
var urlPath = _step4.value;
|
|
10581
|
+
var validation = validateUrlAgainstPattern(urlPath, routePattern);
|
|
10582
|
+
if (!validation.isValid) {
|
|
10583
|
+
errors.push({
|
|
10584
|
+
error: {
|
|
10585
|
+
message: "URL path \"".concat(urlPath, "\" does not match the route pattern for \"").concat(moduleFilePath, "\""),
|
|
10586
|
+
urlPath: urlPath,
|
|
10587
|
+
expectedPath: validation.expectedPath || null
|
|
10588
|
+
}
|
|
10589
|
+
});
|
|
10590
|
+
}
|
|
10591
|
+
}
|
|
10592
|
+
} catch (err) {
|
|
10593
|
+
_iterator4.e(err);
|
|
10594
|
+
} finally {
|
|
10595
|
+
_iterator4.f();
|
|
10596
|
+
}
|
|
10597
|
+
return errors;
|
|
10598
|
+
}
|
|
10599
|
+
};
|
|
10600
|
+
|
|
10601
|
+
/**
|
|
10602
|
+
* The routers whose keys are URL paths of THIS site, and how to read the route
|
|
10603
|
+
* pattern a module of each serves.
|
|
10604
|
+
*
|
|
10605
|
+
* Keyed by router id because that is all a serialized schema carries. A router
|
|
10606
|
+
* that is not in here — `external-url-router` today — has keys that are URLs of
|
|
10607
|
+
* somewhere else, so matching this site's pathname against them is meaningless
|
|
10608
|
+
* rather than merely unsupported.
|
|
10609
|
+
*/
|
|
10610
|
+
var PAGE_ROUTE_PATTERN_PARSERS = {
|
|
10611
|
+
"next-app-router": parseNextJsRoutePattern,
|
|
10612
|
+
"tanstack-router": parseTanStackRoutePattern
|
|
10613
|
+
};
|
|
10614
|
+
|
|
10092
10615
|
/**
|
|
10093
10616
|
* Given a URL pathname (e.g. "/blogs/blog-1") and all serialized module schemas,
|
|
10094
|
-
* finds the
|
|
10095
|
-
* and the source path for that route's content.
|
|
10617
|
+
* finds the page-router module that serves that route and returns the module
|
|
10618
|
+
* file path and the source path for that route's content.
|
|
10096
10619
|
*
|
|
10097
10620
|
* External routers (e.g. external-url-router) are intentionally skipped.
|
|
10098
|
-
* Returns null if no
|
|
10621
|
+
* Returns null if no page-router module matches the pathname.
|
|
10099
10622
|
*/
|
|
10100
10623
|
function getSourcePathFromRoute(pathname, schemas) {
|
|
10101
10624
|
for (var _i = 0, _arr = Object.entries(schemas); _i < _arr.length; _i++) {
|
|
10102
10625
|
var _arr$_i = _slicedToArray(_arr[_i], 2),
|
|
10103
10626
|
moduleFilePath = _arr$_i[0],
|
|
10104
10627
|
schema = _arr$_i[1];
|
|
10105
|
-
if (schema.type !== "record" || schema.router
|
|
10628
|
+
if (schema.type !== "record" || !schema.router) {
|
|
10106
10629
|
continue;
|
|
10107
10630
|
}
|
|
10108
|
-
var
|
|
10631
|
+
var parseRoutePattern = PAGE_ROUTE_PATTERN_PARSERS[schema.router];
|
|
10632
|
+
if (!parseRoutePattern) {
|
|
10633
|
+
continue;
|
|
10634
|
+
}
|
|
10635
|
+
var routePattern = parseRoutePattern(moduleFilePath);
|
|
10109
10636
|
var _validateUrlAgainstPa = validateUrlAgainstPattern(pathname, routePattern),
|
|
10110
10637
|
isValid = _validateUrlAgainstPa.isValid;
|
|
10111
10638
|
if (isValid) {
|
|
@@ -10120,20 +10647,81 @@ function getSourcePathFromRoute(pathname, schemas) {
|
|
|
10120
10647
|
return null;
|
|
10121
10648
|
}
|
|
10122
10649
|
|
|
10650
|
+
/**
|
|
10651
|
+
* Whether a router id is one whose keys are routes of this site.
|
|
10652
|
+
*
|
|
10653
|
+
* The same question `getSourcePathFromRoute` asks, exported because the Studio
|
|
10654
|
+
* asks it too — a page router gets the sitemap and the "Pages" menu, an
|
|
10655
|
+
* external one gets a flat list of URLs — and the two must not disagree about
|
|
10656
|
+
* which is which.
|
|
10657
|
+
*/
|
|
10658
|
+
function isPageRouter(routerId) {
|
|
10659
|
+
return routerId in PAGE_ROUTE_PATTERN_PARSERS;
|
|
10660
|
+
}
|
|
10661
|
+
|
|
10662
|
+
var corePackageJson = {
|
|
10663
|
+
name: "@valbuild/core",
|
|
10664
|
+
version: "0.125.0",
|
|
10665
|
+
"private": false,
|
|
10666
|
+
description: "Val - supercharged hard-coded content",
|
|
10667
|
+
repository: {
|
|
10668
|
+
type: "git",
|
|
10669
|
+
url: "git+https://github.com/valbuild/val.git"
|
|
10670
|
+
},
|
|
10671
|
+
scripts: {
|
|
10672
|
+
typecheck: "tsc --noEmit",
|
|
10673
|
+
test: "jest",
|
|
10674
|
+
"analyze-trace": "npx tsc -p tsconfig.json --skipLibCheck --generateTrace trace; npx -p @typescript/analyze-trace analyze-trace trace; npx speedscope trace/trace.json"
|
|
10675
|
+
},
|
|
10676
|
+
main: "dist/valbuild-core.cjs.js",
|
|
10677
|
+
module: "dist/valbuild-core.esm.js",
|
|
10678
|
+
exports: {
|
|
10679
|
+
".": {
|
|
10680
|
+
module: "./dist/valbuild-core.esm.js",
|
|
10681
|
+
"default": "./dist/valbuild-core.cjs.js"
|
|
10682
|
+
},
|
|
10683
|
+
"./fp": {
|
|
10684
|
+
module: "./fp/dist/valbuild-core-fp.esm.js",
|
|
10685
|
+
"default": "./fp/dist/valbuild-core-fp.cjs.js"
|
|
10686
|
+
},
|
|
10687
|
+
"./patch": {
|
|
10688
|
+
module: "./patch/dist/valbuild-core-patch.esm.js",
|
|
10689
|
+
"default": "./patch/dist/valbuild-core-patch.cjs.js"
|
|
10690
|
+
},
|
|
10691
|
+
"./package.json": "./package.json"
|
|
10692
|
+
},
|
|
10693
|
+
types: "dist/valbuild-core.cjs.d.ts",
|
|
10694
|
+
preconstruct: {
|
|
10695
|
+
entrypoints: [
|
|
10696
|
+
"./index.ts",
|
|
10697
|
+
"./fp/index.ts",
|
|
10698
|
+
"./patch/index.ts"
|
|
10699
|
+
],
|
|
10700
|
+
exports: true
|
|
10701
|
+
},
|
|
10702
|
+
devDependencies: {
|
|
10703
|
+
typescript: "^6.0.3"
|
|
10704
|
+
},
|
|
10705
|
+
dependencies: {
|
|
10706
|
+
"ts-toolbelt": "^9.6.0"
|
|
10707
|
+
},
|
|
10708
|
+
files: [
|
|
10709
|
+
"CHANGELOG.md",
|
|
10710
|
+
"dist",
|
|
10711
|
+
"fp/dist",
|
|
10712
|
+
"fp/package.json",
|
|
10713
|
+
"patch/dist",
|
|
10714
|
+
"patch/package.json"
|
|
10715
|
+
]
|
|
10716
|
+
};
|
|
10717
|
+
|
|
10123
10718
|
var ModuleFilePathSep = "?p=";
|
|
10124
10719
|
var FATAL_ERROR_TYPES = ["no-schema", "no-source", "invalid-id", "no-module", "invalid-patch"];
|
|
10125
10720
|
var DEFAULT_CONTENT_HOST = "https://content.val.build";
|
|
10126
10721
|
var DEFAULT_APP_HOST = "https://admin.val.build";
|
|
10127
10722
|
var Internal = {
|
|
10128
10723
|
VERSION: {
|
|
10129
|
-
core:
|
|
10130
|
-
try {
|
|
10131
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
10132
|
-
return require("../package.json").version;
|
|
10133
|
-
} catch (_unused) {
|
|
10134
|
-
return null;
|
|
10135
|
-
}
|
|
10136
|
-
}()
|
|
10724
|
+
core: corePackageJson.version
|
|
10137
10725
|
},
|
|
10138
10726
|
mediaUrl: mediaUrl,
|
|
10139
10727
|
resolveMedia: resolveMedia,
|
|
@@ -10150,6 +10738,7 @@ var Internal = {
|
|
|
10150
10738
|
splitModuleFilePathAndModulePath: splitModuleFilePathAndModulePath,
|
|
10151
10739
|
joinModuleFilePathAndModulePath: joinModuleFilePathAndModulePath,
|
|
10152
10740
|
nextAppRouter: nextAppRouter,
|
|
10741
|
+
tanstackRouter: tanstackRouter,
|
|
10153
10742
|
externalPageRouter: externalPageRouter,
|
|
10154
10743
|
color: {
|
|
10155
10744
|
parseColor: parseColor,
|
|
@@ -10174,6 +10763,11 @@ var Internal = {
|
|
|
10174
10763
|
isJson: isJson,
|
|
10175
10764
|
getJsonImport: getJsonImport,
|
|
10176
10765
|
resolveJsonValues: resolveJsonValues,
|
|
10766
|
+
isExternal: isExternal,
|
|
10767
|
+
hasInlineExternalEntries: hasInlineExternalEntries,
|
|
10768
|
+
createExternalFileRef: createExternalFileRef,
|
|
10769
|
+
splitExternalFileRef: splitExternalFileRef,
|
|
10770
|
+
isExternalFileRef: isExternalFileRef,
|
|
10177
10771
|
createValPathOfItem: createValPathOfItem,
|
|
10178
10772
|
getSHA256Hash: getSHA256Hash,
|
|
10179
10773
|
initSchema: initSchema,
|
|
@@ -10233,9 +10827,9 @@ var Internal = {
|
|
|
10233
10827
|
function tryJsonParse(str) {
|
|
10234
10828
|
try {
|
|
10235
10829
|
return JSON.parse(str);
|
|
10236
|
-
} catch (
|
|
10830
|
+
} catch (_unused) {
|
|
10237
10831
|
return str;
|
|
10238
10832
|
}
|
|
10239
10833
|
}
|
|
10240
10834
|
|
|
10241
|
-
export { ArraySchema as A, BooleanSchema as B, ColorSchema as C, DEFAULT_CONTENT_HOST as D,
|
|
10835
|
+
export { parseTanStackRoutePattern as $, ArraySchema as A, BooleanSchema as B, ColorSchema as C, DEFAULT_CONTENT_HOST as D, COLOR_FORMATS as E, FATAL_ERROR_TYPES as F, GenericSelector as G, DEFAULT_COLOR_FORMAT as H, Internal as I, DateTimeSchema as J, KeyOfSchema as K, RouteSchema as L, ModuleFilePathSep as M, NumberSchema as N, ObjectSchema as O, PatchError as P, RichTextSchema as Q, RecordSchema as R, Schema as S, LiteralSchema as T, UnionSchema as U, VAL_EXTENSION as V, deserializeSchema as W, previewScope as X, isInlineRender as Y, parseNextJsRoutePattern as Z, _typeof as _, _slicedToArray as a, tanStackSegmentsOfRoutePath as a0, validateUrlAgainstPattern as a1, getSourcePathFromRoute as a2, isPageRouter as a3, _createClass as b, _classCallCheck as c, _toConsumableArray as d, DEFAULT_APP_HOST as e, extractValModules as f, computeValModuleShas as g, hasRemoteFileSchema as h, initVal as i, hasMediaSchema as j, DEFAULT_VAL_REMOTE_HOST as k, derefPatch as l, modules as m, StringSchema as n, ImageSchema as o, FileSchema as p, DateSchema as q, SettingsSchema as r, splitModuleFilePathAndModulePath as s, ASSISTANT_SETTINGS_MAX_LENGTH as t, assistantAvailability as u, SETTINGS_MODULE_CONVENTION as v, isRootModuleFilePath as w, resolveSettingsModule as x, CodeSchema as y, CODE_LANGUAGES as z };
|