untyped icon indicating copy to clipboard operation
untyped copied to clipboard

rewamp untyped into a runtime-friendly lib

Open pi0 opened this issue 2 years ago • 3 comments

Background

Back in time I was developing the untyped library, the idea was to make a unified (build-time) solution to merge type and runtime validation from one source with little or no extra code and use JSON Schema as a unified schema format mainly for handling nuxt config schema.

Currently untyped:

  • Is designed as a build-time utility
  • Uses a superset of JSON Schema for scheme definitions
  • Can Transform source to combine JSDocs and runtime validator into one schema
  • Can Generate TypeScript types and markdown from schema
  • Can normalize an input object with schema and defaults
  • Supports both object schema and function schema

However, it has some limitations:

  • It is not designed with minimum bundle impact to be a runtime library
  • Does not provide convenience API to define the schema (previous proposal: #91)
  • Cannot directly infer typescript types from schema without a build step
  • Does not provide compatibility with other schema validation libraries
  • Does not provide utils uses for validating schema

Future Vision

Untyped should:

  • Provide an (end) user-friendly DX to easily define and validate the schema
  • Be runtime-friendly with minimum bundle impact
  • Provide a way for compatibility with other schema validation libraries
  • Use a unified schema object for validation and definitions

At this point, I am not sure how to make the perfect solution to meet the above criteria. I might also end-up with making a new library if not fitting for one lib. Share the main vision and ideas publicly to gather ideas and myself taking notes.

Similar efforts

Recently I have found out about the (amazing) typeschema project which tries to almost do the same of unifying schema validation libraries. I love it but it has some implementation drawbacks that are not fully tree-shakable (it is fixable with some major changes) but also is not itself trying to make a standard schema nor provide build-time utils like currently untyped does.

There is also JsonTypeDef Standard (RFC) which could be a nice replacement for JSON Schema as a current source of trust.

Schema Validation Libs

Zod

  • Website: https://zod.dev/
  • Repo: https://github.com/colinhacks/zod

Joi

  • Repo: https://github.com/hapijs/joi

Yup

  • Repo: https://github.com/jquense/yup

io-ts

  • Repo: https://github.com/gcanti/io-ts

Runtypes

  • Repo: https://github.com/pelotom/runtypes

Valibot

  • Website: https://valibot.dev/
  • Repo: https://github.com/fabian-hiller/valibot

AJV

  • Website: https://ajv.js.org/

Superstruct

  • Website: https://docs.superstructjs.org/

OW

  • Website: https://sindresorhus.com/ow/

Typebox

  • Repo: https://github.com/sinclairzx81/typebox

Typia

  • Website: https://typia.io/docs/

Deepkit/type

  • Website: https://deepkit.io/library/type

Arktype

  • Website: https://arktype.io/

pi0 avatar Jul 25 '23 16:07 pi0

Notes from @decs (author of typeschema): (https://github.com/unjs/h3/pull/431#issuecomment-1650221199)

we started with a simple logic, inspired by tRPC, but quickly noticed that it wouldn't support other libraries where the validation function lives outside of the schema object (like io-ts, ajv). so we pivoted to the adapter + optional peer dependencies model, and now we're on track to support all major libs this week. and indeed there's a tradeoff: the architecture change increased the LOC.

I can think of 2 alternatives to adding typeschema as a direct dependency, if the LOC is a concern:

  1. making it an optional peer dependency. try dynamically importing typeschema (falling back to no schema validation if not installed) and instructing users to install it on their own
  2. or supporting custom validators with this format: <T>(data: unknown): Promise<T> | T, then asking users to independently install typeschema and use createAssert(schema) (which generates a function on this format)

pi0 avatar Jul 25 '23 17:07 pi0

Another option from typeschema (which I realy like) is to take inspiration from vee-validate vue validation library which support yup and zod out of the box by using abstraction and adapters package like @vee-validate/yup and @vee-validate/zod.

https://vee-validate.logaretm.com/v4/guide/composition-api/getting-started/#form-schema

The benefit would be to keep minimum dependencies, but would need to create and maintain each package.

The caveat I see with typeschema is that it has a lot of peerDependencies which can grow dependencies (recently pnpm has toggled auto-install-peers to true by default https://pnpm.io/next/npmrc#auto-install-peers)

stafyniaksacha avatar Aug 02 '23 13:08 stafyniaksacha

The peer dependencies on typeschema are all optional, just to ensure that you're using a version that's compatible with the adapter. Installing typeschema shouldn't install any peer dependencies.

I looked at the pnpm option you mentioned and it should skip optional peer dependencies as expected.

auto-install-peers

Default: true Type: Boolean When true, any missing non-optional peer dependencies are automatically installed.

I still haven't set my mind on one package vs multiple packages (one per adapter). But I currently lean towards one package to avoid users from having to manually install every adapter they care about (hopefully all). Though it's growing on me the idea of having both: scoped packages for each adapter and one main package will all automatically installed.

decs avatar Aug 02 '23 15:08 decs