@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
|
@@ -1964,7 +1964,7 @@ var union = function union(key) {
|
|
|
1964
1964
|
return new UnionSchema(key, objects);
|
|
1965
1965
|
};
|
|
1966
1966
|
|
|
1967
|
-
var RegEx = /^(https?:\/\/[^/]+)\/file\/p\/([^/]+)\/b\/([^/]+)\/v\/([^/]+)\/h\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
|
|
1967
|
+
var RegEx$1 = /^(https?:\/\/[^/]+)\/file\/p\/([^/]+)\/b\/([^/]+)\/v\/([^/]+)\/h\/([^/]+)\/f\/([^/]+)\/p\/(.+)$/;
|
|
1968
1968
|
function splitRemoteRef(ref) {
|
|
1969
1969
|
if (ref[0] === "/") {
|
|
1970
1970
|
return {
|
|
@@ -1972,7 +1972,7 @@ function splitRemoteRef(ref) {
|
|
|
1972
1972
|
error: "Not a remote ref: " + ref
|
|
1973
1973
|
};
|
|
1974
1974
|
}
|
|
1975
|
-
var match = ref.match(RegEx);
|
|
1975
|
+
var match = ref.match(RegEx$1);
|
|
1976
1976
|
if (!match) {
|
|
1977
1977
|
return {
|
|
1978
1978
|
status: "error",
|
|
@@ -4370,6 +4370,94 @@ function _resolveJsonValues() {
|
|
|
4370
4370
|
return _resolveJsonValues.apply(this, arguments);
|
|
4371
4371
|
}
|
|
4372
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
|
+
|
|
4373
4461
|
/**
|
|
4374
4462
|
* The source type of a `.jsonValues()` record: every entry value is EITHER a
|
|
4375
4463
|
* lazily loaded {@link JsonSource} whose resolved content is the (loosened, see
|
|
@@ -4398,6 +4486,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4398
4486
|
var isJsonValues = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
|
|
4399
4487
|
var previewInput = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : null;
|
|
4400
4488
|
var renderInput = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : null;
|
|
4489
|
+
var externalLabel = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : null;
|
|
4401
4490
|
_classCallCheck(this, RecordSchema);
|
|
4402
4491
|
_this = _callSuper(this, RecordSchema);
|
|
4403
4492
|
_this.item = item;
|
|
@@ -4412,24 +4501,28 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4412
4501
|
_this.isJsonValues = isJsonValues;
|
|
4413
4502
|
_this.previewInput = previewInput;
|
|
4414
4503
|
_this.renderInput = renderInput;
|
|
4504
|
+
_this.externalLabel = externalLabel;
|
|
4415
4505
|
return _this;
|
|
4416
4506
|
}
|
|
4417
4507
|
_inherits(RecordSchema, _Schema);
|
|
4418
4508
|
return _createClass(RecordSchema, [{
|
|
4419
4509
|
key: "describe",
|
|
4420
4510
|
value: function describe(description) {
|
|
4421
|
-
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);
|
|
4422
4512
|
}
|
|
4423
4513
|
}, {
|
|
4424
4514
|
key: "validate",
|
|
4425
4515
|
value: function validate(validationFunction) {
|
|
4426
|
-
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);
|
|
4427
4517
|
}
|
|
4428
4518
|
}, {
|
|
4429
4519
|
key: "executeValidate",
|
|
4430
4520
|
value: function executeValidate(path, src) {
|
|
4431
4521
|
var _this2 = this;
|
|
4432
4522
|
var error = false;
|
|
4523
|
+
if (this.externalLabel !== null) {
|
|
4524
|
+
return this.validateExternal(path, src);
|
|
4525
|
+
}
|
|
4433
4526
|
var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions, {
|
|
4434
4527
|
path: path
|
|
4435
4528
|
});
|
|
@@ -4766,31 +4859,42 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4766
4859
|
}, {
|
|
4767
4860
|
key: "nullable",
|
|
4768
4861
|
value: function nullable() {
|
|
4769
|
-
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);
|
|
4770
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
|
+
*/
|
|
4771
4875
|
}, {
|
|
4772
4876
|
key: "readonly",
|
|
4773
4877
|
value: function readonly() {
|
|
4774
4878
|
var isReadonly = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
4775
|
-
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);
|
|
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);
|
|
4776
4880
|
}
|
|
4777
4881
|
}, {
|
|
4778
4882
|
key: "hidden",
|
|
4779
4883
|
value: function hidden() {
|
|
4780
4884
|
var isHidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
4781
|
-
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);
|
|
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);
|
|
4782
4886
|
}
|
|
4783
4887
|
}, {
|
|
4784
4888
|
key: "router",
|
|
4785
4889
|
value: function router(_router) {
|
|
4786
|
-
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);
|
|
4787
4891
|
}
|
|
4788
4892
|
}, {
|
|
4789
4893
|
key: "remote",
|
|
4790
4894
|
value: function remote() {
|
|
4791
4895
|
return new RecordSchema(this.item, this.opt, this.customValidateFunctions, this.currentRouter, this.keySchema, this.mediaOptions ? _objectSpread2(_objectSpread2({}, this.mediaOptions), {}, {
|
|
4792
4896
|
remote: true
|
|
4793
|
-
}) : 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);
|
|
4794
4898
|
}
|
|
4795
4899
|
|
|
4796
4900
|
/**
|
|
@@ -4832,7 +4936,84 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4832
4936
|
// Empty by construction: the guard above rejects any that were registered.
|
|
4833
4937
|
[], this.currentRouter, this.keySchema, this.mediaOptions, this.isReadonly, this.isHidden, this.description, true,
|
|
4834
4938
|
// Null by construction: the guard above rejects any that was declared.
|
|
4835
|
-
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;
|
|
4836
5017
|
}
|
|
4837
5018
|
}, {
|
|
4838
5019
|
key: "getRouterValidations",
|
|
@@ -4886,7 +5067,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4886
5067
|
}, {
|
|
4887
5068
|
key: "executeSerialize",
|
|
4888
5069
|
value: function executeSerialize() {
|
|
4889
|
-
var _this$renderInput, _this$keySchema, _this$currentRouter, _this$customValidateF;
|
|
5070
|
+
var _this$renderInput, _this$keySchema, _this$currentRouter, _this$customValidateF, _this$externalLabel;
|
|
4890
5071
|
var result = {
|
|
4891
5072
|
type: "record",
|
|
4892
5073
|
render: (_this$renderInput = this.renderInput) !== null && _this$renderInput !== void 0 ? _this$renderInput : undefined,
|
|
@@ -4897,6 +5078,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4897
5078
|
router: (_this$currentRouter = this.currentRouter) === null || _this$currentRouter === void 0 ? void 0 : _this$currentRouter.getRouterId(),
|
|
4898
5079
|
customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0,
|
|
4899
5080
|
jsonValues: this.isJsonValues ? true : undefined,
|
|
5081
|
+
external: (_this$externalLabel = this.externalLabel) !== null && _this$externalLabel !== void 0 ? _this$externalLabel : undefined,
|
|
4900
5082
|
readonly: this.isReadonly,
|
|
4901
5083
|
hidden: this.isHidden,
|
|
4902
5084
|
description: this.description
|
|
@@ -4934,8 +5116,12 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4934
5116
|
if (src === null) {
|
|
4935
5117
|
return res;
|
|
4936
5118
|
}
|
|
4937
|
-
|
|
4938
|
-
|
|
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];
|
|
4939
5125
|
if (itemSrc === null || itemSrc === undefined) {
|
|
4940
5126
|
continue;
|
|
4941
5127
|
}
|
|
@@ -4946,14 +5132,14 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4946
5132
|
// keys, and the caller shows a placeholder for the rest.
|
|
4947
5133
|
continue;
|
|
4948
5134
|
}
|
|
4949
|
-
var subPath = unsafeCreateSourcePath(sourcePath,
|
|
5135
|
+
var subPath = unsafeCreateSourcePath(sourcePath, _key2);
|
|
4950
5136
|
if (scope !== undefined && !scope.wantsUnder(subPath)) {
|
|
4951
5137
|
continue;
|
|
4952
5138
|
}
|
|
4953
5139
|
var itemResult = this.item["executePreview"](subPath, itemSrc, scope);
|
|
4954
5140
|
for (var keyS in itemResult) {
|
|
4955
|
-
var
|
|
4956
|
-
res[
|
|
5141
|
+
var _key3 = keyS;
|
|
5142
|
+
res[_key3] = itemResult[_key3];
|
|
4957
5143
|
}
|
|
4958
5144
|
}
|
|
4959
5145
|
// The entries preview comes from the ITEM schema's own `preview` — the
|
|
@@ -4964,9 +5150,9 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4964
5150
|
// is being shown, only the wanted entries when it is not.
|
|
4965
5151
|
var window = scope !== undefined && !scope.wants(sourcePath) ? scope : null;
|
|
4966
5152
|
var items = [];
|
|
4967
|
-
for (var
|
|
4968
|
-
var _Object$entries$_i = _slicedToArray(_Object$entries[
|
|
4969
|
-
|
|
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],
|
|
4970
5156
|
val = _Object$entries$_i[1];
|
|
4971
5157
|
if (isJson(val)) {
|
|
4972
5158
|
continue; // as above: nothing to select from an un-loaded entry
|
|
@@ -4974,7 +5160,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4974
5160
|
if (val === null || val === undefined) {
|
|
4975
5161
|
continue;
|
|
4976
5162
|
}
|
|
4977
|
-
if (window !== null && !window.wantsUnder(unsafeCreateSourcePath(sourcePath,
|
|
5163
|
+
if (window !== null && !window.wantsUnder(unsafeCreateSourcePath(sourcePath, _key4))) {
|
|
4978
5164
|
continue;
|
|
4979
5165
|
}
|
|
4980
5166
|
// Per KEY, not per record: the closure is user code, and one entry whose
|
|
@@ -4986,14 +5172,14 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
4986
5172
|
var title = _item.title,
|
|
4987
5173
|
subtitle = _item.subtitle,
|
|
4988
5174
|
image = _item.image;
|
|
4989
|
-
items.push([
|
|
5175
|
+
items.push([_key4, {
|
|
4990
5176
|
title: title,
|
|
4991
5177
|
subtitle: subtitle,
|
|
4992
5178
|
image: image
|
|
4993
5179
|
}]);
|
|
4994
5180
|
}
|
|
4995
5181
|
} catch (e) {
|
|
4996
|
-
res[unsafeCreateSourcePath(sourcePath,
|
|
5182
|
+
res[unsafeCreateSourcePath(sourcePath, _key4)] = {
|
|
4997
5183
|
status: "error",
|
|
4998
5184
|
message: e instanceof Error ? e.message : "Unknown error"
|
|
4999
5185
|
};
|
|
@@ -5034,7 +5220,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5034
5220
|
}, {
|
|
5035
5221
|
key: "preview",
|
|
5036
5222
|
value: function preview(select) {
|
|
5037
|
-
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);
|
|
5038
5224
|
}
|
|
5039
5225
|
|
|
5040
5226
|
/**
|
|
@@ -5047,7 +5233,7 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
|
|
|
5047
5233
|
}, {
|
|
5048
5234
|
key: "render",
|
|
5049
5235
|
value: function render(input) {
|
|
5050
|
-
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);
|
|
5051
5237
|
}
|
|
5052
5238
|
}]);
|
|
5053
5239
|
}(Schema);
|
|
@@ -5548,6 +5734,22 @@ function settings() {
|
|
|
5548
5734
|
});
|
|
5549
5735
|
}
|
|
5550
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
|
+
|
|
5551
5753
|
function define(id,
|
|
5552
5754
|
// TODO: `/${string}`
|
|
5553
5755
|
schema, source) {
|
|
@@ -6955,6 +7157,8 @@ function file(options) {
|
|
|
6955
7157
|
/**
|
|
6956
7158
|
* Define a collection of files.
|
|
6957
7159
|
*
|
|
7160
|
+
* Remote is off by default: call `.remote()` on the result to allow remote files.
|
|
7161
|
+
*
|
|
6958
7162
|
* @example
|
|
6959
7163
|
* ```typescript
|
|
6960
7164
|
* const schema = s.files({
|
|
@@ -6969,7 +7173,6 @@ function file(options) {
|
|
|
6969
7173
|
* ```
|
|
6970
7174
|
*/
|
|
6971
7175
|
var files = function files(options) {
|
|
6972
|
-
var _options$remote;
|
|
6973
7176
|
var directory = options.directory;
|
|
6974
7177
|
var itemSchema = new ObjectSchema({
|
|
6975
7178
|
mimeType: new StringSchema({}, false)
|
|
@@ -6978,7 +7181,7 @@ var files = function files(options) {
|
|
|
6978
7181
|
type: "files",
|
|
6979
7182
|
accept: options.accept,
|
|
6980
7183
|
directory: directory,
|
|
6981
|
-
remote:
|
|
7184
|
+
remote: false
|
|
6982
7185
|
});
|
|
6983
7186
|
};
|
|
6984
7187
|
|
|
@@ -8346,7 +8549,7 @@ function router(router, keyOrItem, maybeItem) {
|
|
|
8346
8549
|
*
|
|
8347
8550
|
* `directory` is required — it decides where uploads land, so it is not something
|
|
8348
8551
|
* to be inferred. The rest defaults: any image type (`"image/*"`), nullable alt
|
|
8349
|
-
* text, remote disabled.
|
|
8552
|
+
* text, remote disabled. Call `.remote()` on the result to allow remote images.
|
|
8350
8553
|
*
|
|
8351
8554
|
* @example
|
|
8352
8555
|
* ```typescript
|
|
@@ -8366,7 +8569,7 @@ function router(router, keyOrItem, maybeItem) {
|
|
|
8366
8569
|
* ```
|
|
8367
8570
|
*/
|
|
8368
8571
|
var images = function images(options) {
|
|
8369
|
-
var _options$alt, _options$accept
|
|
8572
|
+
var _options$alt, _options$accept;
|
|
8370
8573
|
var directory = options.directory;
|
|
8371
8574
|
var altSchema = (_options$alt = options.alt) !== null && _options$alt !== void 0 ? _options$alt : string().nullable();
|
|
8372
8575
|
var itemSchema = new ObjectSchema({
|
|
@@ -8379,7 +8582,7 @@ var images = function images(options) {
|
|
|
8379
8582
|
type: "images",
|
|
8380
8583
|
accept: (_options$accept = options.accept) !== null && _options$accept !== void 0 ? _options$accept : "image/*",
|
|
8381
8584
|
directory: directory,
|
|
8382
|
-
remote:
|
|
8585
|
+
remote: false,
|
|
8383
8586
|
altSchema: altSchema,
|
|
8384
8587
|
encode: options.encode
|
|
8385
8588
|
});
|
|
@@ -8457,7 +8660,8 @@ var initVal = function initVal(config) {
|
|
|
8457
8660
|
},
|
|
8458
8661
|
c: {
|
|
8459
8662
|
define: define,
|
|
8460
|
-
json: json
|
|
8663
|
+
json: json,
|
|
8664
|
+
external: external
|
|
8461
8665
|
},
|
|
8462
8666
|
s: s,
|
|
8463
8667
|
config: config
|
|
@@ -9254,9 +9458,10 @@ function _extractValModules() {
|
|
|
9254
9458
|
* The one answer to that question. There used to be two — `hasRemoteFileSchema`
|
|
9255
9459
|
* in the server, gating whether `/save` demands remote credentials, and
|
|
9256
9460
|
* `findRequiredRemoteFiles` in the Studio, gating the `/remote/settings` fetch —
|
|
9257
|
-
* and they disagreed about `s.images({
|
|
9258
|
-
* remote media record, the server's did not, because a media
|
|
9259
|
-
* serializes as a `record` of metadata rather than as an image
|
|
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.
|
|
9260
9465
|
*
|
|
9261
9466
|
* The server's answer was the wrong one, and silently so. With it false,
|
|
9262
9467
|
* `/save` runs `saveOrUploadFiles` in `skip-remote` mode, and that mode does not
|
|
@@ -9349,6 +9554,85 @@ function hasRemoteFileSchema(schema) {
|
|
|
9349
9554
|
}
|
|
9350
9555
|
}
|
|
9351
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
|
+
|
|
9352
9636
|
var DEFAULT_VAL_REMOTE_HOST = "https://remote.val.build";
|
|
9353
9637
|
|
|
9354
9638
|
var PatchError = /*#__PURE__*/_createClass(function PatchError(message) {
|
|
@@ -9493,6 +9777,79 @@ function mediaPathOf(value) {
|
|
|
9493
9777
|
return typeof path === "string" ? path : null;
|
|
9494
9778
|
}
|
|
9495
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
|
+
|
|
9496
9853
|
// NOTE: the segments must match the ref built by createRemoteRef below and the RegEx in splitRemoteRef.
|
|
9497
9854
|
|
|
9498
9855
|
function createRemoteRef(remoteHost, _ref) {
|
|
@@ -9553,7 +9910,7 @@ function deserializeSchema(serialized) {
|
|
|
9553
9910
|
return schema;
|
|
9554
9911
|
}
|
|
9555
9912
|
function deserializeSchemaImpl(serialized) {
|
|
9556
|
-
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;
|
|
9557
9914
|
switch (serialized.type) {
|
|
9558
9915
|
case "string":
|
|
9559
9916
|
return new StringSchema(_objectSpread2(_objectSpread2({}, serialized.options), {}, {
|
|
@@ -9614,7 +9971,10 @@ function deserializeSchemaImpl(serialized) {
|
|
|
9614
9971
|
altSchema: serialized.alt ? deserializeSchema(serialized.alt) : undefined
|
|
9615
9972
|
} : undefined, false, false, serialized.description, (_serialized$jsonValue = serialized.jsonValues) !== null && _serialized$jsonValue !== void 0 ? _serialized$jsonValue : false,
|
|
9616
9973
|
// The preview closure cannot survive serialization; the render can.
|
|
9617
|
-
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);
|
|
9618
9978
|
case "keyOf":
|
|
9619
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);
|
|
9620
9980
|
case "route":
|
|
@@ -10091,23 +10451,190 @@ function parseNextJsRoutePattern(moduleFilePath) {
|
|
|
10091
10451
|
return [];
|
|
10092
10452
|
}
|
|
10093
10453
|
|
|
10454
|
+
/**
|
|
10455
|
+
* Parse a TanStack Router route pattern out of a Val module file path.
|
|
10456
|
+
*
|
|
10457
|
+
* TanStack Router's file conventions are not Next's, so this is a different
|
|
10458
|
+
* parser rather than a flag on the one above. A Val module for a route lives
|
|
10459
|
+
* beside the route file and is named the same way — `routes/posts.$postId.tsx`
|
|
10460
|
+
* is served content by `routes/posts.$postId.val.ts` — so the pattern is the
|
|
10461
|
+
* file path with the conventions applied:
|
|
10462
|
+
*
|
|
10463
|
+
* - `.` and `/` both separate segments (`posts.$postId.val.ts` and
|
|
10464
|
+
* `posts/$postId.val.ts` are the same route)
|
|
10465
|
+
* - `$param` is a dynamic segment, `$` on its own is a splat
|
|
10466
|
+
* - `index` is the directory's own route and contributes no segment
|
|
10467
|
+
* - `route` is a layout for the directory, likewise
|
|
10468
|
+
* - `(group)` folders and `_pathless` layout segments are not in the URL
|
|
10469
|
+
* - a trailing `_` on a segment opts out of nesting and is not in the URL
|
|
10470
|
+
*
|
|
10471
|
+
* The result is expressed in the SAME vocabulary the Next parser uses
|
|
10472
|
+
* (`[param]`, `[...param]`), because everything downstream — validation, the
|
|
10473
|
+
* sitemap, the key inputs in the Studio — is written against that vocabulary
|
|
10474
|
+
* and there is no reason for two.
|
|
10475
|
+
*
|
|
10476
|
+
* - /src/routes/posts.$postId.val.ts -> ["posts", "[postId]"]
|
|
10477
|
+
* - /routes/posts/$postId.val.ts -> ["posts", "[postId]"]
|
|
10478
|
+
* - /src/routes/index.val.ts -> []
|
|
10479
|
+
* - /src/routes/files.$.val.ts -> ["files", "[..._splat]"]
|
|
10480
|
+
* - /src/routes/(app)/_layout.about.val.ts -> ["about"]
|
|
10481
|
+
*/
|
|
10482
|
+
function parseTanStackRoutePattern(moduleFilePath) {
|
|
10483
|
+
var segments = tanStackRouteSegments(moduleFilePath);
|
|
10484
|
+
if (segments === null) {
|
|
10485
|
+
return [];
|
|
10486
|
+
}
|
|
10487
|
+
return segments;
|
|
10488
|
+
}
|
|
10489
|
+
|
|
10490
|
+
/**
|
|
10491
|
+
* The segments, or `null` when the path is not a TanStack route module at all.
|
|
10492
|
+
*
|
|
10493
|
+
* Distinct from `parseTanStackRoutePattern`'s empty array, which is a real
|
|
10494
|
+
* answer: the root route `/` has no segments.
|
|
10495
|
+
*/
|
|
10496
|
+
function tanStackRouteSegments(moduleFilePath) {
|
|
10497
|
+
if (!moduleFilePath || typeof moduleFilePath !== "string") {
|
|
10498
|
+
return null;
|
|
10499
|
+
}
|
|
10500
|
+
var match = moduleFilePath.match(/^(?:\/src)?\/routes\/(.+)\.val\.[tj]sx?$/);
|
|
10501
|
+
if (!match) {
|
|
10502
|
+
return null;
|
|
10503
|
+
}
|
|
10504
|
+
return tanStackSegmentsOfRoutePath(match[1]);
|
|
10505
|
+
}
|
|
10506
|
+
|
|
10507
|
+
/**
|
|
10508
|
+
* The URL segments of a TanStack route path, given relative to `routes/`.
|
|
10509
|
+
*
|
|
10510
|
+
* Exported because the Studio derives the same pattern from the same file path
|
|
10511
|
+
* and must not disagree with validation about what a route is.
|
|
10512
|
+
*/
|
|
10513
|
+
function tanStackSegmentsOfRoutePath(routePath) {
|
|
10514
|
+
// `.` is a separator exactly like `/`, so flatten both before looking at any
|
|
10515
|
+
// segment: `posts/$postId.edit` and `posts.$postId.edit` are one route.
|
|
10516
|
+
var rawSegments = routePath.split("/").flatMap(function (part) {
|
|
10517
|
+
return part.split(".");
|
|
10518
|
+
}).filter(function (part) {
|
|
10519
|
+
return part !== "";
|
|
10520
|
+
});
|
|
10521
|
+
var segments = [];
|
|
10522
|
+
var _iterator3 = result._createForOfIteratorHelper(rawSegments),
|
|
10523
|
+
_step3;
|
|
10524
|
+
try {
|
|
10525
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
10526
|
+
var rawSegment = _step3.value;
|
|
10527
|
+
// A route group: a folder that organises files without appearing in the URL.
|
|
10528
|
+
if (rawSegment.startsWith("(") && rawSegment.endsWith(")")) {
|
|
10529
|
+
continue;
|
|
10530
|
+
}
|
|
10531
|
+
// A pathless layout route. `_layout` nests its children without adding a
|
|
10532
|
+
// segment; `index`/`route` are the directory's own route and its layout.
|
|
10533
|
+
if (rawSegment.startsWith("_")) {
|
|
10534
|
+
continue;
|
|
10535
|
+
}
|
|
10536
|
+
if (rawSegment === "index" || rawSegment === "route") {
|
|
10537
|
+
continue;
|
|
10538
|
+
}
|
|
10539
|
+
// A trailing `_` opts the segment out of layout nesting; the URL keeps the
|
|
10540
|
+
// name without it.
|
|
10541
|
+
var segment = rawSegment.endsWith("_") ? rawSegment.slice(0, -1) : rawSegment;
|
|
10542
|
+
if (segment === "$") {
|
|
10543
|
+
// A splat. Named `_splat` because that is the param name TanStack gives
|
|
10544
|
+
// it, so `useValRoute(pageVal, params)` can be handed the route's own
|
|
10545
|
+
// params object unchanged.
|
|
10546
|
+
segments.push("[..._splat]");
|
|
10547
|
+
continue;
|
|
10548
|
+
}
|
|
10549
|
+
if (segment.startsWith("$")) {
|
|
10550
|
+
segments.push("[".concat(segment.slice(1), "]"));
|
|
10551
|
+
continue;
|
|
10552
|
+
}
|
|
10553
|
+
segments.push(segment);
|
|
10554
|
+
}
|
|
10555
|
+
} catch (err) {
|
|
10556
|
+
_iterator3.e(err);
|
|
10557
|
+
} finally {
|
|
10558
|
+
_iterator3.f();
|
|
10559
|
+
}
|
|
10560
|
+
return segments;
|
|
10561
|
+
}
|
|
10562
|
+
|
|
10563
|
+
/**
|
|
10564
|
+
* The router for a TanStack Router (and TanStack Start) app.
|
|
10565
|
+
*
|
|
10566
|
+
* Like `nextAppRouter` this does not belong in core — it is here for the same
|
|
10567
|
+
* reason that one is: the serialized schema carries only a router id, so the
|
|
10568
|
+
* thing that turns an id back into a validator has to be somewhere every
|
|
10569
|
+
* consumer can reach.
|
|
10570
|
+
*/
|
|
10571
|
+
var tanstackRouter = {
|
|
10572
|
+
getRouterId: function getRouterId() {
|
|
10573
|
+
return "tanstack-router";
|
|
10574
|
+
},
|
|
10575
|
+
validate: function validate(moduleFilePath, urlPaths) {
|
|
10576
|
+
var routePattern = parseTanStackRoutePattern(moduleFilePath);
|
|
10577
|
+
var errors = [];
|
|
10578
|
+
var _iterator4 = result._createForOfIteratorHelper(urlPaths),
|
|
10579
|
+
_step4;
|
|
10580
|
+
try {
|
|
10581
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
10582
|
+
var urlPath = _step4.value;
|
|
10583
|
+
var validation = validateUrlAgainstPattern(urlPath, routePattern);
|
|
10584
|
+
if (!validation.isValid) {
|
|
10585
|
+
errors.push({
|
|
10586
|
+
error: {
|
|
10587
|
+
message: "URL path \"".concat(urlPath, "\" does not match the route pattern for \"").concat(moduleFilePath, "\""),
|
|
10588
|
+
urlPath: urlPath,
|
|
10589
|
+
expectedPath: validation.expectedPath || null
|
|
10590
|
+
}
|
|
10591
|
+
});
|
|
10592
|
+
}
|
|
10593
|
+
}
|
|
10594
|
+
} catch (err) {
|
|
10595
|
+
_iterator4.e(err);
|
|
10596
|
+
} finally {
|
|
10597
|
+
_iterator4.f();
|
|
10598
|
+
}
|
|
10599
|
+
return errors;
|
|
10600
|
+
}
|
|
10601
|
+
};
|
|
10602
|
+
|
|
10603
|
+
/**
|
|
10604
|
+
* The routers whose keys are URL paths of THIS site, and how to read the route
|
|
10605
|
+
* pattern a module of each serves.
|
|
10606
|
+
*
|
|
10607
|
+
* Keyed by router id because that is all a serialized schema carries. A router
|
|
10608
|
+
* that is not in here — `external-url-router` today — has keys that are URLs of
|
|
10609
|
+
* somewhere else, so matching this site's pathname against them is meaningless
|
|
10610
|
+
* rather than merely unsupported.
|
|
10611
|
+
*/
|
|
10612
|
+
var PAGE_ROUTE_PATTERN_PARSERS = {
|
|
10613
|
+
"next-app-router": parseNextJsRoutePattern,
|
|
10614
|
+
"tanstack-router": parseTanStackRoutePattern
|
|
10615
|
+
};
|
|
10616
|
+
|
|
10094
10617
|
/**
|
|
10095
10618
|
* Given a URL pathname (e.g. "/blogs/blog-1") and all serialized module schemas,
|
|
10096
|
-
* finds the
|
|
10097
|
-
* and the source path for that route's content.
|
|
10619
|
+
* finds the page-router module that serves that route and returns the module
|
|
10620
|
+
* file path and the source path for that route's content.
|
|
10098
10621
|
*
|
|
10099
10622
|
* External routers (e.g. external-url-router) are intentionally skipped.
|
|
10100
|
-
* Returns null if no
|
|
10623
|
+
* Returns null if no page-router module matches the pathname.
|
|
10101
10624
|
*/
|
|
10102
10625
|
function getSourcePathFromRoute(pathname, schemas) {
|
|
10103
10626
|
for (var _i = 0, _arr = Object.entries(schemas); _i < _arr.length; _i++) {
|
|
10104
10627
|
var _arr$_i = _slicedToArray(_arr[_i], 2),
|
|
10105
10628
|
moduleFilePath = _arr$_i[0],
|
|
10106
10629
|
schema = _arr$_i[1];
|
|
10107
|
-
if (schema.type !== "record" || schema.router
|
|
10630
|
+
if (schema.type !== "record" || !schema.router) {
|
|
10108
10631
|
continue;
|
|
10109
10632
|
}
|
|
10110
|
-
var
|
|
10633
|
+
var parseRoutePattern = PAGE_ROUTE_PATTERN_PARSERS[schema.router];
|
|
10634
|
+
if (!parseRoutePattern) {
|
|
10635
|
+
continue;
|
|
10636
|
+
}
|
|
10637
|
+
var routePattern = parseRoutePattern(moduleFilePath);
|
|
10111
10638
|
var _validateUrlAgainstPa = validateUrlAgainstPattern(pathname, routePattern),
|
|
10112
10639
|
isValid = _validateUrlAgainstPa.isValid;
|
|
10113
10640
|
if (isValid) {
|
|
@@ -10122,20 +10649,81 @@ function getSourcePathFromRoute(pathname, schemas) {
|
|
|
10122
10649
|
return null;
|
|
10123
10650
|
}
|
|
10124
10651
|
|
|
10652
|
+
/**
|
|
10653
|
+
* Whether a router id is one whose keys are routes of this site.
|
|
10654
|
+
*
|
|
10655
|
+
* The same question `getSourcePathFromRoute` asks, exported because the Studio
|
|
10656
|
+
* asks it too — a page router gets the sitemap and the "Pages" menu, an
|
|
10657
|
+
* external one gets a flat list of URLs — and the two must not disagree about
|
|
10658
|
+
* which is which.
|
|
10659
|
+
*/
|
|
10660
|
+
function isPageRouter(routerId) {
|
|
10661
|
+
return routerId in PAGE_ROUTE_PATTERN_PARSERS;
|
|
10662
|
+
}
|
|
10663
|
+
|
|
10664
|
+
var corePackageJson = {
|
|
10665
|
+
name: "@valbuild/core",
|
|
10666
|
+
version: "0.125.0",
|
|
10667
|
+
"private": false,
|
|
10668
|
+
description: "Val - supercharged hard-coded content",
|
|
10669
|
+
repository: {
|
|
10670
|
+
type: "git",
|
|
10671
|
+
url: "git+https://github.com/valbuild/val.git"
|
|
10672
|
+
},
|
|
10673
|
+
scripts: {
|
|
10674
|
+
typecheck: "tsc --noEmit",
|
|
10675
|
+
test: "jest",
|
|
10676
|
+
"analyze-trace": "npx tsc -p tsconfig.json --skipLibCheck --generateTrace trace; npx -p @typescript/analyze-trace analyze-trace trace; npx speedscope trace/trace.json"
|
|
10677
|
+
},
|
|
10678
|
+
main: "dist/valbuild-core.cjs.js",
|
|
10679
|
+
module: "dist/valbuild-core.esm.js",
|
|
10680
|
+
exports: {
|
|
10681
|
+
".": {
|
|
10682
|
+
module: "./dist/valbuild-core.esm.js",
|
|
10683
|
+
"default": "./dist/valbuild-core.cjs.js"
|
|
10684
|
+
},
|
|
10685
|
+
"./fp": {
|
|
10686
|
+
module: "./fp/dist/valbuild-core-fp.esm.js",
|
|
10687
|
+
"default": "./fp/dist/valbuild-core-fp.cjs.js"
|
|
10688
|
+
},
|
|
10689
|
+
"./patch": {
|
|
10690
|
+
module: "./patch/dist/valbuild-core-patch.esm.js",
|
|
10691
|
+
"default": "./patch/dist/valbuild-core-patch.cjs.js"
|
|
10692
|
+
},
|
|
10693
|
+
"./package.json": "./package.json"
|
|
10694
|
+
},
|
|
10695
|
+
types: "dist/valbuild-core.cjs.d.ts",
|
|
10696
|
+
preconstruct: {
|
|
10697
|
+
entrypoints: [
|
|
10698
|
+
"./index.ts",
|
|
10699
|
+
"./fp/index.ts",
|
|
10700
|
+
"./patch/index.ts"
|
|
10701
|
+
],
|
|
10702
|
+
exports: true
|
|
10703
|
+
},
|
|
10704
|
+
devDependencies: {
|
|
10705
|
+
typescript: "^6.0.3"
|
|
10706
|
+
},
|
|
10707
|
+
dependencies: {
|
|
10708
|
+
"ts-toolbelt": "^9.6.0"
|
|
10709
|
+
},
|
|
10710
|
+
files: [
|
|
10711
|
+
"CHANGELOG.md",
|
|
10712
|
+
"dist",
|
|
10713
|
+
"fp/dist",
|
|
10714
|
+
"fp/package.json",
|
|
10715
|
+
"patch/dist",
|
|
10716
|
+
"patch/package.json"
|
|
10717
|
+
]
|
|
10718
|
+
};
|
|
10719
|
+
|
|
10125
10720
|
var ModuleFilePathSep = "?p=";
|
|
10126
10721
|
var FATAL_ERROR_TYPES = ["no-schema", "no-source", "invalid-id", "no-module", "invalid-patch"];
|
|
10127
10722
|
var DEFAULT_CONTENT_HOST = "https://content.val.build";
|
|
10128
10723
|
var DEFAULT_APP_HOST = "https://admin.val.build";
|
|
10129
10724
|
var Internal = {
|
|
10130
10725
|
VERSION: {
|
|
10131
|
-
core:
|
|
10132
|
-
try {
|
|
10133
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
10134
|
-
return require("../package.json").version;
|
|
10135
|
-
} catch (_unused) {
|
|
10136
|
-
return null;
|
|
10137
|
-
}
|
|
10138
|
-
}()
|
|
10726
|
+
core: corePackageJson.version
|
|
10139
10727
|
},
|
|
10140
10728
|
mediaUrl: mediaUrl,
|
|
10141
10729
|
resolveMedia: resolveMedia,
|
|
@@ -10152,6 +10740,7 @@ var Internal = {
|
|
|
10152
10740
|
splitModuleFilePathAndModulePath: splitModuleFilePathAndModulePath,
|
|
10153
10741
|
joinModuleFilePathAndModulePath: joinModuleFilePathAndModulePath,
|
|
10154
10742
|
nextAppRouter: nextAppRouter,
|
|
10743
|
+
tanstackRouter: tanstackRouter,
|
|
10155
10744
|
externalPageRouter: externalPageRouter,
|
|
10156
10745
|
color: {
|
|
10157
10746
|
parseColor: parseColor,
|
|
@@ -10176,6 +10765,11 @@ var Internal = {
|
|
|
10176
10765
|
isJson: isJson,
|
|
10177
10766
|
getJsonImport: getJsonImport,
|
|
10178
10767
|
resolveJsonValues: resolveJsonValues,
|
|
10768
|
+
isExternal: isExternal,
|
|
10769
|
+
hasInlineExternalEntries: hasInlineExternalEntries,
|
|
10770
|
+
createExternalFileRef: createExternalFileRef,
|
|
10771
|
+
splitExternalFileRef: splitExternalFileRef,
|
|
10772
|
+
isExternalFileRef: isExternalFileRef,
|
|
10179
10773
|
createValPathOfItem: createValPathOfItem,
|
|
10180
10774
|
getSHA256Hash: getSHA256Hash,
|
|
10181
10775
|
initSchema: initSchema,
|
|
@@ -10235,7 +10829,7 @@ var Internal = {
|
|
|
10235
10829
|
function tryJsonParse(str) {
|
|
10236
10830
|
try {
|
|
10237
10831
|
return JSON.parse(str);
|
|
10238
|
-
} catch (
|
|
10832
|
+
} catch (_unused) {
|
|
10239
10833
|
return str;
|
|
10240
10834
|
}
|
|
10241
10835
|
}
|
|
@@ -10284,11 +10878,17 @@ exports.derefPatch = derefPatch;
|
|
|
10284
10878
|
exports.deserializeSchema = deserializeSchema;
|
|
10285
10879
|
exports.extractValModules = extractValModules;
|
|
10286
10880
|
exports.getSourcePathFromRoute = getSourcePathFromRoute;
|
|
10881
|
+
exports.hasMediaSchema = hasMediaSchema;
|
|
10287
10882
|
exports.hasRemoteFileSchema = hasRemoteFileSchema;
|
|
10288
10883
|
exports.initVal = initVal;
|
|
10289
10884
|
exports.isInlineRender = isInlineRender;
|
|
10885
|
+
exports.isPageRouter = isPageRouter;
|
|
10290
10886
|
exports.isRootModuleFilePath = isRootModuleFilePath;
|
|
10291
10887
|
exports.modules = modules;
|
|
10888
|
+
exports.parseNextJsRoutePattern = parseNextJsRoutePattern;
|
|
10889
|
+
exports.parseTanStackRoutePattern = parseTanStackRoutePattern;
|
|
10292
10890
|
exports.previewScope = previewScope;
|
|
10293
10891
|
exports.resolveSettingsModule = resolveSettingsModule;
|
|
10294
10892
|
exports.splitModuleFilePathAndModulePath = splitModuleFilePathAndModulePath;
|
|
10893
|
+
exports.tanStackSegmentsOfRoutePath = tanStackSegmentsOfRoutePath;
|
|
10894
|
+
exports.validateUrlAgainstPattern = validateUrlAgainstPattern;
|