@beignet/core
Version:
Core framework primitives for Beignet
91 lines • 2.79 kB
JavaScript
/**
* Validate data using a Standard Schema validator
*/
async function validateSchema(schema, data) {
const result = await schema["~standard"].validate(data);
if (result.issues?.length) {
const message = result.issues
.map((issue) => {
const path = issue.path !== undefined
? Array.isArray(issue.path)
? issue.path.join(".")
: String(issue.path)
: "";
return path ? `${path}: ${issue.message}` : issue.message;
})
.join("; ");
throw new Error(`Validation failed: ${message}`);
}
if ("value" in result) {
return result.value;
}
throw new Error("Invalid Standard Schema result: missing value");
}
/**
* Check if data is valid according to a Standard Schema
*/
async function isValid(schema, data) {
const result = await schema["~standard"].validate(data);
return !result.issues?.length && "value" in result;
}
/**
* Builder class for creating Value Objects.
*/
class ValueObjectBuilder {
cfg;
constructor(cfg) {
this.cfg = cfg;
}
/**
* Set the schema for this value object.
*/
schema(s) {
return new ValueObjectBuilder({ ...this.cfg, schema: s });
}
/**
* Finalize the value object definition.
*/
build() {
if (!this.cfg.schema) {
throw new Error(`Value object "${this.cfg.name}" is missing a schema`);
}
const schemaToUse = this.cfg.schema;
const def = {
name: this.cfg.name,
schema: schemaToUse,
async create(input) {
return validateSchema(schemaToUse, input);
},
async isValid(input) {
return isValid(schemaToUse, input);
},
// Type is undefined at runtime - used only for TypeScript type inference via `typeof ValueObject.Type`
Type: undefined,
};
return def;
}
}
/**
* Create a new value object builder.
*
* Value objects are schema-backed primitives for domain concepts such as email
* addresses or money values. Beignet does not add a runtime brand; the schema
* output controls the runtime value.
*
* @example
* ```ts
* const Email = defineValueObject("Email")
* .schema(z.string().email())
* .build();
*
* type Email = typeof Email.Type;
*
* const email = await Email.create("test@example.com"); // OK
* const isValid = await Email.isValid("test@example.com"); // true
* ```
*/
export function defineValueObject(name) {
// biome-ignore lint/suspicious/noExplicitAny: Initial schema type is never, will be set via .schema()
return new ValueObjectBuilder({ name });
}
//# sourceMappingURL=value-object.js.map