0.8.0 • Published 6 months ago

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

Weekly downloads
-
License
MIT
Repository
github
Last release
6 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

6 months ago

0.7.0

8 months ago

0.5.0

8 months ago

0.4.0

8 months ago

0.6.0

8 months ago

0.3.3

8 months ago

0.3.2

8 months ago

0.3.1

8 months ago

0.3.0

8 months ago

0.2.0

8 months ago

0.1.0

8 months ago