0.8.0 • Published 8 months ago

@yamaimo-illus/typespec-to-zod v0.8.0

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

typespec-to-zod

This library is effortlessly converts YAML from TypeSpec into Zod schemas.

Usage

Provide the CLI with the input/output file path and additional options as shown below.

typespec-to-zod -i path/to/openapi.yaml -o path/to/generated.ts -c -p -q -n nullish

Command-line options

The tool supports a variety of command-line options to customize the output:

OptionsDescriptionDefault
-i, --inputPath to the OpenAPI YAML file.N/A
-o, --outputOutput file path for the generated schema.N/A
-c, --componentsFlag to generate components.false
-p, --pathsFlag to generate paths.false
-q, --queriesFlag to generate queries.false
-n, --nullable-modeSet null handling mode: nullish/optionalnullish

Examples

Supported TypeSpec built-in types

See Built-in types | TypeSpec.

Numeric types

These are the mappings from TypeSpec numeric types to Zod:

TypeSpec TypeZod Type Conversion
numericz.number()
integerz.number()
floatz.number()
int64z.number().int()
int32z.number().int()
int16z.number().int()
int8z.number().int()
safeintz.number().int()
uint64z.number().int()
uint32z.number().int()
uint16z.number().int()
uint8z.number().int()
float32z.number()
float64z.number()
decimalz.number()
decimal128z.number()

Example TypeSpec:

model NumericTypes {
  numericProperty: numeric;
  integerProperty: integer;
  floatProperty: float;
  int64Property: int64;
  int32Property: int32;
  int16Property: int16;
  int8Property: int8;
  safeintProperty: safeint;
  uint64Property: uint64;
  uint32Property: uint32;
  uint16Property: uint16;
  uint8Property: uint8;
  float32Property: float32;
  float64Property: float64;
  decimalProperty: decimal;
  decimal128Property: decimal128;
}

Generated Zod schema:

export const schemaNumericTypes = z.object({
  numericProperty: z.number(),
  integerProperty: z.number(),
  floatProperty: z.number(),
  int64Property: z.number().int(),
  int32Property: z.number().int(),
  int16Property: z.number().int(),
  int8Property: z.number().int(),
  safeintProperty: z.number().int(),
  uint64Property: z.number().int(),
  uint32Property: z.number().int(),
  uint16Property: z.number().int(),
  uint8Property: z.number().int(),
  float32Property: z.number(),
  float64Property: z.number(),
  decimalProperty: z.number(),
  decimal128Property: z.number()
})

Date and Time types

These types involve conversions that consider date and time formatting:

TypeSpec TypeZod Type Conversion
plainDatez.string().date()
plainTimez.string().time()
utcDateTimez.string().datetime()
offsetDateTimez.string().datetime()
durationz.string().duration

Example TypeSpec:

model DateAndTimeTypes {
  plainDateProperty: plainDate;
  plainTimeProperty: plainTime;
  utcDateTimeProperty: utcDateTime;
  offsetDateTimeProperty: offsetDateTime;
  durationProperty: duration;
}

Generated Zod schema:

export const schemaDateAndTimeTypes = z.object({
  plainDateProperty: z.string().date(),
  plainTimeProperty: z.string().time(),
  utcDateTimeProperty: z.string().datetime(),
  offsetDateTimeProperty: z.string().datetime(),
  durationProperty: z.string().duration()
})

Other core types

These are additional core types and their mappings:

TypeSpec TypeZod Type Conversion
bytesNot supported but it generated as z.string()
stringz.string()
booleanz.boolean()
nullz.unknown()
Array\<Element>z.array(z.Element())
Record\<Element>Not supported but it generated as z.object({})
unknownz.unknown()
voidNOT SUPPORTED
neverNOT SUPPORTED

Example TypeSpec:

model OtherCoreTypes {
  bytesProperty: bytes;
  stringProperty: string;
  booleanProperty: boolean;
  nullProperty: null;
  ArrayProperty: numeric[];
  recordProperty: Record<numeric>;
  unknownProperty: unknown;
  // voidProperty: void; Not Supported
  // neverProperty: never; Not Supported
}

Generated Zod schema:

export const schemaOtherCoreTypes = z.object({
  bytesProperty: z.string(),
  stringProperty: z.string(),
  booleanProperty: z.boolean(),
  nullProperty: z.unknown(),
  ArrayProperty: z.array(z.number()),
  recordProperty: z.record(z.string(), z.number()),
  unknownProperty: z.unknown()
})

String types

The tool also supports string-specific types and their conversions:

TypeSpec TypeZod Type Conversion
urlz.string().url()

Example TypeSpec:

model StringTypes {
  urlProperty: url;
}

Generated Zod schema:

export const schemaStringTypes = z.object({
  urlProperty: z.string().url()
})

Supported TypeSpec Decorators

These decorators in TypeSpec can be converted to specific constraints in Zod schemas:

TypeSpec DecoratorZod Type Conversion
@minItems().min()
@maxItems().max()
@minLength().min()
@maxLength().max()
@minValue().gte()
@maxValue().lte()
@exclusiveMinimum().gt()
@exclusiveMaximum().lt()

Example TypeSpec:

model TypeSpecDecorators {
  @minItems(1)
  @maxItems(5)
  items: string[];

  @minLength(1)
  @maxLength(5)
  name: string;

  @minValue(1)
  @maxValue(5)
  age: int16;

  @minValueExclusive(1)
  @maxValueExclusive(5)
  count: int16;
}

Generated Zod schema:

export const schemaTypeSpecDecorators = z.object({
  items: z.array(z.string()).min(1).max(5),
  name: z.string().min(1).max(5),
  age: z.number().int().gte(1).lte(5),
  count: z.number().int().gt(1).lt(5)
})

Supported TypeSpec Format Decorators

These format decorators in TypeSpec can be converted to specific constraints in Zod schemas:

TypeSpec FormatZod Type Conversion
@format("date-time").datetime()
@format("date").date()
@format("time").time()
@format("duration").duration()
@format("ip").ip()
@format("email").email()
@format("uuid").uuid()
@format("cuid").cuid()
@format("cuid2").cuid2()
@format("uri").url()
@format("url").url()

Extended Syntax for Doc Decorator

By using the zod: identifier within a doc comment, you can instruct the typespec-to-zod to generate Zod schemas with specific requirements.

This feature provides greater flexibility and control over the validation rules directly from the TypeSpec model.

Example TypeSpec:

model ExtendedSyntaxForDocDecorator {
  @doc("Username zod: z.string().min(2, { message: 'Must be 2 or more characters long' })")
  name: string;
}

Generated Zod schema:

export const schemaExtendedSyntaxForDocDecorator = z.object({
  // Username
  name: z.string().min(2, { message: 'Must be 2 or more characters long' })
})

Contributing

Contributions are welcome!

If you find a bug or have a feature request, feel free to open an issue or submit a pull request.

License

This project is licensed under the MIT License.

0.8.0

8 months ago

0.7.0

10 months ago

0.5.0

10 months ago

0.4.0

10 months ago

0.6.0

10 months ago

0.3.3

10 months ago

0.3.2

10 months ago

0.3.1

10 months ago

0.3.0

10 months ago

0.2.0

10 months ago

0.1.0

10 months ago