npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ymgn-dev/zodify

v2.5.0

Published

TypeSpec to Zod schema generator

Downloads

373

Readme

Zodify

A tool that generates Zod type definitions from OpenAPI YAML.

[!WARNING] Please note that this tool only targets YAML generated based on TypeSpec definitions.

Japanese version: README_ja.md

Setup

git clone [email protected]:ymgn-dev/zodify.git
cd zodify
npm run build

Usage

Specify the OpenAPI YAML file with the -i option and the output .ts file with the -o option.

node dist/index.mjs -i ./path/to/openapi.yaml -o ./path/to/output.ts

Supported Syntax

Comment Decorators

You can add comments to models and properties using the @doc() decorator.

@doc("This is a comment for the model")
model SampleModel {
  @doc("This is the model's ID")
  @format("uuid")
  id: string;

  @doc("Creation date")
  createdAt: utcDateTime;

  @doc("Update date")
  updatedAt: utcDateTime;
}

The above model will be converted as follows:

// This is a comment for the model
export const sampleModelSchema = z.object({
  // This is the model's ID
  id: z.string().uuid(),

  // Creation date
  createdAt: z.string().datetime(),

  // Update date
  updatedAt: z.string().datetime(),
})

Additionally, if you want to generate Zod schemas that cannot be expressed using the standard decorators below, you can use an extended notation for the @doc() decorator. Write regular comments (optional) to the left of zod:, and the Zod schema on the right. Note that when using this extended notation, the type-specific decorators below will be ignored.

model SampleModel {
  @doc("Email address, unset defaults to an empty string zod: z.union([z.string().email(), z.literal("")]).default("")")
  email: string;
}
export const sampleModelSchema = z.object({
  // Email address, unset defaults to an empty string
  email: z.union([z.string().email(), z.literal('')]).default(''),
})

Models

This syntax is used for defining top-level models.

| Syntax | Notes | | --- | --- | | model Element { } | Converts to z.object({ ... }) | | model Elements is Array<Element> { } | Converts to z.array(...) | | enum Element { } | Converts to z.enum([ ... ]) |

model SampleModel {
  a: numeric;
  b: string;
}

model ArraySampleModel is Array<SampleModel> {}

enum EnumSample {
  A,
  B,
  C
}

Scalars

This syntax is used for defining types that do not exist in TypeSpec.

@doc("UUID")
@format("uuid")
scalar Uuid extends string;

@doc("Integer greater than 100")
@minValueExclusive(100)
scalar Gt100 extends int32;

The above model will be converted as follows:

// UUID
export const uuidSchema = z.string().uuid()

// Integer greater than 100
export const gt100Schema = z.number().int().gt(100)

Numbers

| Type | Notes | | --- | --- | | integer | Converts to z.number().int() | | int64 | Converts to z.number().int() | | int32 | Converts to z.number().int() | | int16 | Converts to z.number().int() | | int8 | Converts to z.number().int() | | safeint | Converts to z.number().int() | | uint64 | Converts to z.number().int() | | uint32 | Converts to z.number().int() | | uint16 | Converts to z.number().int() | | uint8 | Converts to z.number().int() | | numeric | Converts to z.number() | | float | Converts to z.number() | | float64 | Converts to z.number() | | float32 | Converts to z.number() | | decimal | Converts to z.number() | | decimal128 | Converts to z.number() |

| Decorator | Notes | | --- | --- | | @minValue(42) | Converts to .gte(42) | | @maxValue(42) | Converts to .lte(42) | | @minValueExclusive(8) | Converts to .gt(8) | | @maxValueExclusive(8) | Converts to .lt(8) |

Additional Notes

To make properties in a TypeSpec model optional, add a ? after the property name. You can also set default values using =. It is possible to combine both optional and default values.

model Sample {
  a?: int32;
  b: integer = 42;
  c?: float = 3.14;
}

The above model will be converted as follows:

export const sampleSchema = z.object({
  a: z.number().int().optional(),
  b: z.number().int().default(42),
  c: z.number().optional().default(3.14),
})
@doc("Numeric values")
model NumericValues {
  @minValue(42.6)
  @maxValue(95.8)
  a: numeric;

  @minValueExclusive(8)
  @maxValueExclusive(16)
  b: integer;

  @doc("Optional input")
  c: float;

  @doc("Has a default value")
  d: int64 = 42;
  e: int32;
  f: int16;
  g: int8;
  h: safeint;
  i: uint64;
  j: uint32;
  k: uint16;
  l: uint8;
  m: float64;
  n: float32;
  o: decimal;
  p: decimal128;
}

Strings

[!WARNING] bytes is not supported because it is not defined in Zod.

[!NOTE] Some types are not supported in TypeSpec but are supported in Zod. These types can be converted using the @format() decorator described below.

| Type | Notes | | --- | --- | | string | Converts to z.string() | | plainDate | Converts to z.string().date() | | plainTime | Converts to z.string().time() | | utcDateTime | Converts to z.string().datetime() | | offsetDateTime | Converts to z.string().datetime() | | duration | Converts to z.string().duration() | | url | Converts to z.string().url() |

| Decorator | Notes | | --- | --- | | @minLength(42) | Converts to .min(42) | | @maxLength(42) | Converts to .max(42) | | @format("date") | Equivalent to plainDate type, converts to .date() | | @format("time") | Equivalent to plainTime type, converts to .time() | | @format("date-time") | Equivalent to utcDateTime and offsetDateTime types, converts to .datetime() | | @format("duration") | Equivalent to duration type, converts to .duration() | | @format("uri") | Equivalent to url type, converts to .url() | | @format("email") | Converts to .email() | | @format("uuid") | Converts to .uuid() | | @format("cuid") | Converts to .cuid() | | @format("ip") | Converts to .ip() |

Additional Notes

To make properties in a TypeSpec model optional, add a ? after the property name. You can also set default values using =. It is possible to combine both optional and default values.

model Sample {
  a?: string;
  b: string = "Sample string";
  c?: string = "Sample string";
}

The above model will be converted as follows:

export const sampleSchema = z.object({
  a: z.string().optional(),
  b: z.string().default('Sample string'),
  c: z.string().optional().default('Sample string'),
})
@doc("String values")
model StringValues {
  @minLength(42)
  @maxLength(96)
  a: string;

  b: plainDate;
  c: plainTime;
  d: utcDateTime;
  e: offsetDateTime;
  f: duration;
  g: url;

  @format("email")
  h: string;

  @format("uuid")
  i: string;
}

Booleans

| Type | Notes | | --- | --- | | boolean | Converts to z.boolean() |

Additional Notes

To make properties in a TypeSpec model optional, add a ? after the property name. You can also set default values using =. It is possible to combine both optional and default values.

model Sample {
  a?: boolean;
  b: boolean = true;
  c?: boolean = false;
}

The above model will be converted as follows:

export const sampleSchema = z.object({
  a: z.boolean().optional(),
  b: z.boolean().default(true),
  c: z.boolean().optional().default(false),
})
@doc("Boolean values")
model BooleanValues {
  a: boolean;
}

Arrays, Objects, and Enums

[!WARNING] Record<Element> is not currently supported.

| Type | Notes | | --- | --- | | Element[] | Converts to z.array(elementSchema) |

| Decorator | Notes | | --- | --- | | @minItems(42) | Converts to .min(42) | | @maxItems(42) | Converts to .max(42) |

Additional Notes

To make properties in a TypeSpec model optional, add a ? after the property name. You can also set default values using =. For arrays, TypeSpec requires default values to be written as #[...]. It is possible to combine both optional and default values.

model OtherModel {
  @format("uuid")
  id: string;
}

@doc("Array test")
model Sample {
  a?: string[];
  b: string[] = #["sample1", "sample2"];
  c?: string[] = #[];
  d: int32[] = #[4, 8, 32];
  e: OtherModel[] = #[];
}

The above model will be converted as follows:

export const otherModelSchema = z.object({
  id: z.string().uuid(),
})

// Array test
export const sampleSchema = z.object({
  a: z.array(z.string()).optional(),
  b: z.array(z.string()).default(['sample1', 'sample2']),
  c: z.array(z.string()).optional().default([]),
  d: z.array(z.number().int()).default([4, 8, 32]),
  e: z.array(otherModelSchema).default([]),
})
@doc("Arrays")
model ArrayValues {
  @minItems(42)
  @maxItems(96)
  a: string[];

  b: OtherModel[];
}

Others

[!WARNING] null, unknown, void, and never are not currently supported.