@orbit-utils/zod-to-model-definition v0.1.0
@orbit-utils/zod-to-model-definition
Define your RecordSchema using Zod.
Before:
const planetModelDefinition = {
attributes: {
name: {type: "string"},
classification: {type: "string"},
atmosphere: {type: "boolean"},
mass: {type: "number"},
},
relationships: {
solarSystem: {kind: "hasOne", type: "solarSystem", inverse: "planets"},
moons: {kind: "hasMany", type: "moon", inverse: "planet"},
},
};After:
import {m, zodToModelDefinition} from "@orbit-utils/zod-to-model-definition";
import {z} from "zod";
const planetZodSchema = z.object({
type: z.literal("planet"),
id: z.string().optional(),
attributes: z.object({
name: z.string(),
classification: z.enum(["terrestrial", "gaseous"]),
atmosphere: z.boolean(),
mass: z.number().positive().finite(),
}),
relationships: z.object({
solarSystem: m.relationship("hasOne", "solarSystem").inverse("planets"),
moons: m.relationship("hasMany", "moon").inverse("planet"),
}),
});
const planetModelDefinition = zodToModelDefinition(planetZodSchema);Usage
Install using your preferred Node.js package manager. For example:
pnpm add @orbit-utils/zod-to-model-definitionImport and enjoy!
import {zodToModelDefinition} from "@orbit-utils/zod-to-model-definition";For facilitating special model definition attributes (such as inverse, dependent: "delete" and meta) in your Zod schema, the library provides custom ZodTypes through m:
import {m} from "@orbit-utils/zod-to-model-definition";
m.relationship("hasOne", "solarSystem").inverse("planets");
m.relationship("hasMany", "moon").inverse("planet");
m.attribute(z.number().positive().finite()).definitionMeta({unit: "kg"});Advantages of using Zod to define your RecordSchema
- You can infer TypeScript types from your Zod schema.
type Planet = z.infer<typeof planetZodSchema>; // same as… interface Planet extends UninitializedRecord { type: "planet"; ... } // …except you don't have to maintain separate interface definitions - Zod allows for a more granular schema definition (more granular types, more granular validation).
classification: { type: "string"; } vs.z.enum(["terrestrial", "gaseous"]); mass: { type: "number"; } vs.z.number().positive().finite();- You can configure Orbit to use Zod's validation instead of its own with
validateFor.
- You can configure Orbit to use Zod's validation instead of its own with
Additional features
- Maps
.optional()tovalidation.required: falseand.nullable()tovalidation.notNull: false.
API reference
zodToModelDefinition
import type {ModelDefinition} from "@orbit/records";
import type {AnyZodObject} from "zod";
export function zodToModelDefinition(zodSchema: AnyZodObject): ModelDefinition;ZodKey
Extends ZodType.
Zod schema counterpart for KeyDefinition.
Can be created by calling m.key.
import type {ZodType} from "zod";
export function key(zodType?: ZodType<string>): ZodKey;.definitionMeta
ZodKey.definitionMeta: (definitionMeta: {[key: string]: unknown}) => ZodKeyZodAttribute
Extends ZodType.
Zod schema counterpart for AttributeDefinition.
Can be created by calling m.attribute.
import type {ZodTypeAny} from "zod";
export function attribute(zodType?: ZodTypeAny): ZodAttribute;.definitionMeta
ZodAttribute.definitionMeta: (definitionMeta: {[key: string]: unknown}) => ZodAttribute.serialization
ZodAttribute.serialization: (serialization: {[key: string]: unknown}) => ZodAttribute.deserialization
ZodAttribute.deserialization: (deserialization: {[key: string]: unknown}) => ZodAttributeZodRelationship
Extends ZodType.
Zod schema counterpart for RelationshipDefinition.
Can be created by calling m.relationship.
import type {ZodTypeAny} from "zod";
export function relationship(
kind: "hasOne" | "hasMany",
type?: string | string[],
): ZodRelationship;.definitionMeta
ZodRelationship.definitionMeta: (definitionMeta: {[key: string]: unknown}) => ZodRelationship.inverse
ZodRelationship.inverse: (relationshipName: string) => ZodRelationship.dependentRemove
ZodRelationship.dependentRemove: () => ZodRelationship.links
Schema for the links object that can appear on your record. (See RecordRelationship.)
import type {Link} from "@orbit/records";
import type {ZodType} from "zod";
ZodRelationship.links: (schema: ZodType<{[key: string]: Link} | undefined>) => ZodRelationship.meta
Schema for the meta object that can appear on your record. (See RecordRelationship.)
import type {ZodType} from "zod";
ZodRelationship.meta: (schema: ZodType<{[key: string]: unknown} | undefined>) => ZodRelationship2 years ago