Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeBox 0.31.0 and Transform Type Provider #99

Closed
wants to merge 3 commits into from
Closed

TypeBox 0.31.0 and Transform Type Provider #99

wants to merge 3 commits into from

Conversation

sinclairzx81
Copy link
Contributor

@sinclairzx81 sinclairzx81 commented Aug 13, 2023

Checklist


Overview

This PR updates TypeBox to 0.31.0 and implements experimental support for a new codec system called Transform types. This feature became available on TypeBox version 0.31.0. High level documentation on the feature can be found at the following Url.

https://github.com/sinclairzx81/typebox#types-transform

Transform Types

const Timestamp = Type.Transform(Type.Number())
  .Decode(value => new Date(value))      // number > Date
  .Encode(value => value.getTime())      // Date > number

Transform types are a new feature that can enable Fastify to automatically decode Json values on http requests, as well as encode them back to Json on http responses. This feature works by integrating the new TypeBox Transform infrastructure with the Fastify validationCompiler and preSerialization stages for requests and responses.

This PR implements this feature such that Fastify users leveraging transforms would only see a decoded Json value (and associated decoded inference type) appear within a Fastify route. This feature was written specifically with JavaScript Date decoding in mind (which tends to be an issue that many users run into when transmitting data using Json), but also as a general enhancement for users leveraging Fastify Type Providers.

Transform types work by allowing users to implement small mapping codecs at the type level. The transforms themselves work like regular types, however they have the ability to infer as both encoded and decoded type via new static inference infrastructure implemented in TypeBox. The effect of these types is that they enable users to define json value transformations once (for example a transform that decodes a number into a Date), then reuse that transform by embedding it in larger schematics.

The feature is intended to work as transparently as possible, allowing users to rely on surrounding infrastructure (in this case Fastify + Type Provider) to handle encoding and decoding automatically. This allows users to operate on the intended decoded value without being too concerned about how that value is encoded over the wire.

The following is the example included in the updated README which demonstrates decoding a json number value (representing a timestamp) into a JavaScript Date object.

import { TypeBoxTransformProvider } from '@fastify-type-provider-typebox/transform'
import { Type } from '@fastify-type-provider-typebox'
import Fastify from 'fastify'

// Sets up the validationCompiler and preSerialization hook
const fastify = TypeBoxTransformProvider(Fastify())

// Converts Json number into Date objects
const Timestamp = Type.Transform(Type.Number())
  .Decode(value => new Date(value))      // input: number > Date
  .Encode(value => value.getTime())      // output: Date > number

// Route
fastify.post('/date', {
  schema: {
    body: Timestamp,                      // number
    response: { 200: Timestamp }          // number
  }
}, (req, res) => {
  const { body } = req.body               // Date
  res.send(body)                          // Date
})

Compatibility

TypeBox 0.31.0 is fully compatible with 0.30.0, so it's possible to update TypeBox without this feature. However as the TypeBox Transform infrastructure is new, it's not possible to integrate Transforms as standard without a major semver on this package.

As such, I've made the TypeBoxTransformProvider a sub module import from /transform (which shouldn't impact users on previous versions of TypeBox), but it would be good to test via a npm dev tag revision just to make sure. I've also set things up such that when this package goes a major revision tick, it's possible to uncomment the export in index.ts (I've left some notes in /src/index.ts as reminder documentation)

Submitting for consideration and review
S

@sinclairzx81
Copy link
Contributor Author

@mcollina Hi! Hey, it should be possible to merge through #98 before considering this PR (note: there's no breaking changes on 0.31.0 if just bumping the minor revision range)

For this PR, I've actually carried out a couple of project refactoring's which would require more of an in-depth review (with the refactoring work mostly moving the provider under /src and making this transform opt-in (and to avoid a major semver)). Project configurations could use a review from the TS team just to make sure everything is setup correctly.

@sinclairzx81
Copy link
Contributor Author

@mcollina Hiya, might close off this PR.

I had another look at getting the CI range tests to work this morning and still having some problems there. It would be technically possible to write something to conditionally run the transform tests if >= 0.31.0 (specific to these missing Encode/Decode functions). However getting the compiler to conditionally build differently when < 0.31.0 is just a bit too awkward (same would apply for the tsd type checking tool).

There would be ways to pull in additional build infrastructure to make all this work, but for a temporary configuration to avoid a major semver, I'm thinking it's probably just easier to go a major semver (just to keep the project infrastructure simple) ... so will defer the PR now.

Will keep the implementation around on https://github.com/sinclairzx81/fastify-type-provider-typebox for a later time.

Cheers!

@benevbright
Copy link

great work, is it ongoing? :)

@kibertoad
Copy link
Member

@sinclairzx81 Any plans to release this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants