shelving
Version:
Toolkit for using data in JavaScript.
54 lines (53 loc) • 2.15 kB
JavaScript
import { isData } from "../util/data.js";
import { omitProps, pickProps } from "../util/object.js";
import { mapProps } from "../util/transform.js";
import { validateData } from "../util/validate.js";
import { NULLABLE } from "./NullableSchema.js";
import { OPTIONAL } from "./OptionalSchema.js";
import { Schema } from "./Schema.js";
/** Validate a data object. */
export class DataSchema extends Schema {
props;
constructor({ one = "item", title = "Item", props, value: partialValue, ...options }) {
// Build default value from props and partial value.
const value = { ...mapProps(props, _getSchemaValue), ...partialValue };
super({ one, title, value, ...options });
this.props = props;
}
validate(unsafeValue = this.value) {
if (!isData(unsafeValue))
throw "Must be object";
return validateData(unsafeValue, this.props);
}
/** Make a new `DataSchema` that only uses a defined subset of the current props. */
pick(...keys) {
return new DataSchema({ ...this, props: pickProps(this.props, ...keys) });
}
/** Make a new `DataSchema` that omits one or more of the current props. */
omit(...keys) {
return new DataSchema({ ...this, props: omitProps(this.props, ...keys) });
}
}
function _getSchemaValue([, { value }]) {
return value;
}
/** Create a `DataSchema` for a set of properties. */
export const DATA = (props) => new DataSchema({ props });
/** Valid data object with specifed properties, or `null` */
export const NULLABLE_DATA = (props) => NULLABLE(new DataSchema({ props }));
export function PARTIAL(source) {
const props = source instanceof DataSchema ? source.props : source;
return new DataSchema({
props: mapProps(props, _optionalProp),
});
}
function _optionalProp([, v]) {
return OPTIONAL(v);
}
/** Create a `DataSchema` that validates a data item, i.e. it has a string or number `.id` identifier property. */
export function ITEM(id, schemas) {
const props = schemas instanceof DataSchema ? schemas.props : schemas;
return new DataSchema({
props: { id, ...props },
});
}